ccgo 3.4.2

A high-performance C++ cross-platform build CLI
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
# Android Development

Complete guide for building C++ libraries for Android with CCGO.

## Overview

CCGO provides comprehensive Android support with:

- **Multi-architecture builds**: arm64-v8a, armeabi-v7a, x86, x86_64
- **AAR packaging**: Ready-to-use Android Archive format
- **Gradle integration**: Seamless integration with Android Studio projects
- **JNI support**: Automatic JNI wrapper generation
- **Maven publishing**: Publish to Maven Local, Central, or private repositories
- **Docker builds**: Build without local Android SDK/NDK installation

## Prerequisites

### Option 1: Local Development

**Required:**
- Android SDK (API level 21+)
- Android NDK (r21+, recommended: r25+)
- CMake (3.18+)
- Python (3.8+)

**Installation:**

```bash
# Install Android Studio (includes SDK)
# Download from https://developer.android.com/studio

# Set environment variables
export ANDROID_HOME=$HOME/Android/Sdk
export ANDROID_NDK=$ANDROID_HOME/ndk/25.2.9519653

# Verify installation
ccgo check android --verbose
```

### Option 2: Docker-Based Development

**Required:**
- Docker Desktop

```bash
# Build with Docker (no local SDK/NDK needed)
ccgo build android --docker
```

First build downloads prebuilt image (~3.5GB, 5-10 minutes). Subsequent builds use cached image.

## Quick Start

### Create New Project

```bash
# Create new Android-compatible project
ccgo new my-android-lib
cd my-android-lib/my-android-lib

# Build for Android
ccgo build android
```

### Build Single Architecture

```bash
# Build for arm64-v8a only
ccgo build android --arch arm64-v8a
```

### Build Multiple Architectures

```bash
# Build for arm64-v8a and armeabi-v7a
ccgo build android --arch arm64-v8a,armeabi-v7a

# Build all architectures (default)
ccgo build android
```

### Build Options

```bash
# Release build (optimized)
ccgo build android --release

# Debug build (with symbols)
ccgo build android --debug

# Clean build
ccgo build android --clean

# Docker build
ccgo build android --docker

# Link type control
ccgo build android --link-type static   # Static library only
ccgo build android --link-type shared   # Shared library only
ccgo build android --link-type both     # Both (default)
```

## Output Structure

After building, find artifacts in `target/android/`:

```
target/android/
├── MY-ANDROID-LIB_ANDROID_SDK-1.0.0.zip      # Main package
├── MY-ANDROID-LIB_ANDROID_SDK-1.0.0-SYMBOLS.zip  # Debug symbols
└── build_info.json                            # Build metadata
```

### Main Package Structure

```
MY-ANDROID-LIB_ANDROID_SDK-1.0.0.zip
├── lib/
│   ├── static/
│   │   ├── armeabi-v7a/
│   │   │   └── libmy-android-lib.a
│   │   ├── arm64-v8a/
│   │   │   └── libmy-android-lib.a
│   │   ├── x86/
│   │   │   └── libmy-android-lib.a
│   │   └── x86_64/
│   │       └── libmy-android-lib.a
│   └── shared/
│       ├── armeabi-v7a/
│       │   └── libmy-android-lib.so
│       ├── arm64-v8a/
│       │   └── libmy-android-lib.so
│       ├── x86/
│       │   └── libmy-android-lib.so
│       └── x86_64/
│           └── libmy-android-lib.so
├── haars/
│   └── my-android-lib-release.aar
├── include/
│   └── my-android-lib/
│       ├── my-android-lib.h
│       └── version.h
└── build_info.json
```

### Symbols Package Structure

```
MY-ANDROID-LIB_ANDROID_SDK-1.0.0-SYMBOLS.zip
└── obj/
    ├── armeabi-v7a/
    │   └── libmy-android-lib.so  # Unstripped with debug symbols
    ├── arm64-v8a/
    │   └── libmy-android-lib.so
    ├── x86/
    │   └── libmy-android-lib.so
    └── x86_64/
        └── libmy-android-lib.so
```

## Configuration

### CCGO.toml

Configure Android-specific settings:

```toml
[package]
name = "my-android-lib"
version = "1.0.0"

[library]
type = "both"  # Build both static and shared libraries

[android]
min_sdk_version = 21          # Android 5.0 (Lollipop)
target_sdk_version = 33       # Android 13
ndk_version = "25.2.9519653"  # Specific NDK version
stl = "c++_static"            # STL type: c++_static or c++_shared
architectures = ["arm64-v8a", "armeabi-v7a", "x86_64"]  # Optional: limit architectures

[build]
cpp_standard = "17"
compile_flags = ["-Wall", "-Wextra"]
```

### Android Configuration Options

| Option | Type | Description | Default |
|--------|------|-------------|---------|
| `min_sdk_version` | integer | Minimum Android API level | `21` |
| `target_sdk_version` | integer | Target Android API level | `33` |
| `ndk_version` | string | Specific NDK version | Latest installed |
| `stl` | string | STL type: `c++_static`, `c++_shared` | `c++_static` |
| `architectures` | array | Target ABIs to build | All supported |

### Supported Architectures

| ABI | Architecture | Description |
|-----|-------------|-------------|
| `arm64-v8a` | ARM 64-bit | Modern Android devices (recommended) |
| `armeabi-v7a` | ARM 32-bit | Legacy Android devices |
| `x86_64` | Intel 64-bit | Emulators, tablets, Chrome OS |
| `x86` | Intel 32-bit | Legacy emulators |

**Recommendation:** Build `arm64-v8a` and `armeabi-v7a` for production apps.

## AAR Integration

### Using AAR in Android Project

**1. Copy AAR to project:**

```bash
# Copy AAR from build output
cp target/android/MY-ANDROID-LIB_ANDROID_SDK-1.0.0.zip .
unzip MY-ANDROID-LIB_ANDROID_SDK-1.0.0.zip
cp haars/my-android-lib-release.aar android-app/libs/
```

**2. Configure app/build.gradle.kts:**

```kotlin
android {
    // ...
}

dependencies {
    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar"))))
    // or
    implementation(files("libs/my-android-lib-release.aar"))
}
```

**3. Use in Java/Kotlin:**

```kotlin
class MainActivity : AppCompatActivity() {
    companion object {
        init {
            System.loadLibrary("my-android-lib")
        }
    }

    // Declare native methods
    external fun nativeMethod(): String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Call native method
        val result = nativeMethod()
        Log.d("Native", "Result: $result")
    }
}
```

## JNI Integration

### Automatic JNI Wrapper

CCGO can generate JNI wrappers automatically:

**C++ Header (include/my-android-lib/my-android-lib.h):**

```cpp
#pragma once

#include <string>

namespace my_android_lib {

class MyLib {
public:
    static std::string get_version();
    static int calculate(int a, int b);
};

} // namespace my_android_lib
```

**Generated JNI Wrapper (auto-generated):**

```cpp
#include <jni.h>
#include "my-android-lib/my-android-lib.h"

extern "C" {

JNIEXPORT jstring JNICALL
Java_com_example_mylib_MyLib_getVersion(JNIEnv* env, jclass) {
    std::string version = my_android_lib::MyLib::get_version();
    return env->NewStringUTF(version.c_str());
}

JNIEXPORT jint JNICALL
Java_com_example_mylib_MyLib_calculate(JNIEnv*, jclass, jint a, jint b) {
    return my_android_lib::MyLib::calculate(a, b);
}

} // extern "C"
```

### Manual JNI Implementation

**Create src/jni/my_jni.cpp:**

```cpp
#include <jni.h>
#include <string>
#include "my-android-lib/my-android-lib.h"

extern "C" {

JNIEXPORT jstring JNICALL
Java_com_example_MyNativeLib_stringFromJNI(JNIEnv* env, jobject /* this */) {
    std::string hello = my_android_lib::MyLib::get_version();
    return env->NewStringUTF(hello.c_str());
}

JNIEXPORT jint JNICALL
Java_com_example_MyNativeLib_add(JNIEnv*, jobject, jint a, jint b) {
    return my_android_lib::MyLib::calculate(a, b);
}

} // extern "C"
```

**Java/Kotlin side:**

```kotlin
package com.example

class MyNativeLib {
    external fun stringFromJNI(): String
    external fun add(a: Int, b: Int): Int

    companion object {
        init {
            System.loadLibrary("my-android-lib")
        }
    }
}
```

## Gradle Integration

### Using CCGO Gradle Plugins

CCGO provides Gradle convention plugins for standardized Android builds.

**settings.gradle.kts:**

```kotlin
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
    }
}
```

**app/build.gradle.kts:**

```kotlin
plugins {
    id("com.android.library")
    id("com.mojeter.ccgo.gradle.android.library")
    id("com.mojeter.ccgo.gradle.android.library.native")
}

android {
    namespace = "com.example.mylib"
    compileSdk = 33

    defaultConfig {
        minSdk = 21
    }

    ndkVersion = "25.2.9519653"
}

ccgoNative {
    projectPath.set(file("../"))  // Path to CCGO project root
    buildType.set("release")       // or "debug"
    architectures.set(listOf("arm64-v8a", "armeabi-v7a"))
}
```

## Publishing

### Maven Local (Development)

```bash
# Publish to Maven Local for testing
ccgo publish android --registry local

# Location: ~/.m2/repository/com/example/my-android-lib/1.0.0/
```

### Maven Central (Production)

**1. Configure credentials:**

Create `~/.gradle/gradle.properties`:

```properties
mavenCentralUsername=your-username
mavenCentralPassword=your-password
signing.keyId=12345678
signing.password=your-key-password
signing.secretKeyRingFile=/Users/you/.gnupg/secring.gpg
```

**2. Publish:**

```bash
ccgo publish android --registry official
```

### Private Maven Repository

```bash
ccgo publish android --registry private \
    --url https://maven.example.com/releases
```

### Using Published Library

**app/build.gradle.kts:**

```kotlin
dependencies {
    implementation("com.example:my-android-lib:1.0.0")
}
```

## Advanced Topics

### Multi-Module Projects

**Project structure:**

```
my-project/
├── CCGO.toml
├── lib1/
│   ├── CCGO.toml
│   └── src/
└── lib2/
    ├── CCGO.toml (depends on lib1)
    └── src/
```

**lib2/CCGO.toml:**

```toml
[dependencies]
lib1 = { path = "../lib1" }
```

### Custom CMake Configuration

**CMakeLists.txt:**

```cmake
cmake_minimum_required(VERSION 3.18)

# CCGO automatically provides:
# - ${CCGO_CMAKE_DIR}: Path to CCGO cmake utilities
# - ${ANDROID_ABI}: Current architecture being built
# - ${ANDROID_PLATFORM}: Android API level

include(${CCGO_CMAKE_DIR}/CMakeUtils.cmake)

# Custom Android-specific configuration
if(ANDROID)
    # Add Android-specific compiler flags
    add_compile_options(-fPIC)

    # Link against Android libraries
    find_library(LOG_LIB log)
    find_library(ANDROID_LIB android)

    target_link_libraries(${PROJECT_NAME}
        ${LOG_LIB}
        ${ANDROID_LIB}
    )
endif()
```

### Proguard Rules

**Create proguard-rules.pro:**

```proguard
# Keep native methods
-keepclasseswithmembernames class * {
    native <methods>;
}

# Keep JNI exported methods
-keep class com.example.mylib.** { *; }
```

### App Size Optimization

**1. Strip unneeded symbols (automatic in release builds):**

```bash
ccgo build android --release
```

**2. Use only required architectures:**

```toml
[android]
architectures = ["arm64-v8a"]  # Drop 32-bit support if not needed
```

**3. Enable link-time optimization:**

```toml
[build]
link_flags = ["-flto"]
```

**4. Split APKs by ABI:**

**app/build.gradle.kts:**

```kotlin
android {
    splits {
        abi {
            isEnable = true
            reset()
            include("arm64-v8a", "armeabi-v7a")
            isUniversalApk = false
        }
    }
}
```

## Troubleshooting

### Common Issues

#### NDK Not Found

```
Error: Android NDK not found
```

**Solution:**

```bash
# Install NDK via Android Studio: Tools → SDK Manager → SDK Tools → NDK

# Or set manually
export ANDROID_NDK=$ANDROID_HOME/ndk/25.2.9519653

# Verify
ccgo check android --verbose
```

#### Architecture Mismatch

```
Error: UnsatisfiedLinkError: dlopen failed: library "libmy-android-lib.so" not found
```

**Solution:**

Ensure AAR contains the architecture your device/emulator uses:

```bash
# Check AAR contents
unzip -l my-android-lib-release.aar | grep "\.so$"

# Rebuild with correct architecture
ccgo build android --arch arm64-v8a
```

#### C++ Standard Mismatch

```
Error: undefined reference to std::__cxx11::...
```

**Solution:**

Ensure consistent C++ standard across dependencies:

```toml
[build]
cpp_standard = "17"  # Match with dependencies

[android]
stl = "c++_static"  # Or c++_shared
```

#### Missing Symbols

```
Error: undefined reference to 'my_function'
```

**Solution:**

Check that all source files are compiled:

```bash
# Enable verbose build
ccgo build android --verbose

# Check CMakeLists.txt includes all sources
```

### Docker Build Issues

#### Docker Not Running

```
Error: Cannot connect to the Docker daemon
```

**Solution:**

```bash
# Start Docker Desktop
open -a Docker  # macOS

# Verify
docker ps
```

#### Image Pull Failure

```
Error: failed to pull image ccgo-builder-android
```

**Solution:**

```bash
# Retry with manual pull
docker pull ccgogroup/ccgo-builder-android:latest

# Or use local build
cd ccgo/dockers/
docker build -t ccgo-builder-android -f Dockerfile.android .
```

### Performance Issues

#### Slow First Build

**Normal:** First build compiles all dependencies (~10-30 minutes).

**Optimization:**

```bash
# Use prebuilt dependencies (future feature)
ccgo install --prebuilt

# Enable ccache
export USE_CCACHE=1
export CCACHE_DIR=$HOME/.ccache
```

#### Incremental Build Not Working

```bash
# Clean CMake cache
rm -rf cmake_build/android/

# Rebuild
ccgo build android
```

## Best Practices

### 1. Version Management

```toml
[package]
version = "1.0.0"  # Update before release
```

```bash
# Create git tag
ccgo tag v1.0.0 --push
```

### 2. Architecture Selection

```toml
[android]
# Production: arm64-v8a + armeabi-v7a (covers 99%+ devices)
architectures = ["arm64-v8a", "armeabi-v7a"]

# Development: arm64-v8a only (faster builds)
# architectures = ["arm64-v8a"]
```

### 3. STL Choice

```toml
[android]
# Prefer c++_static (no runtime dependency)
stl = "c++_static"

# Use c++_shared only if multiple native libraries share STL
# stl = "c++_shared"
```

### 4. Dependency Management

```toml
[dependencies]
# Pin to specific versions for reproducibility
spdlog = { git = "https://github.com/gabime/spdlog.git", tag = "v1.12.0" }

# Use CCGO.lock for exact dependency resolution
```

### 5. Testing

```bash
# Build and test locally
ccgo build android --arch arm64-v8a
ccgo test android

# Test AAR in sample app before publishing
```

### 6. CI/CD

```yaml
# .github/workflows/android.yml
name: Android Build

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Build Android
        run: |
          pip install ccgo
          ccgo build android --docker

      - name: Test
        run: ccgo test android --docker

      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: android-libs
          path: target/android/*.zip
```

## Examples

### Complete Project

See [ccgo-now](https://github.com/zhlinh/ccgo-now) for a complete Android project example.

### Minimal Example

```cpp
// include/mylib/mylib.h
#pragma once
#include <string>

namespace mylib {
    std::string get_greeting();
    int add(int a, int b);
}

// src/mylib.cpp
#include "mylib/mylib.h"

namespace mylib {
    std::string get_greeting() {
        return "Hello from C++!";
    }

    int add(int a, int b) {
        return a + b;
    }
}
```

**Build:**

```bash
ccgo build android --arch arm64-v8a
```

**Use in Android:**

```kotlin
class MainActivity : AppCompatActivity() {
    init {
        System.loadLibrary("mylib")
    }

    external fun getGreeting(): String
    external fun add(a: Int, b: Int): Int

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val greeting = getGreeting()
        val result = add(2, 3)

        Log.d("MyLib", "$greeting, 2+3=$result")
    }
}
```

## Resources

### Official Documentation

- [Android NDK Documentation]https://developer.android.com/ndk
- [JNI Specification]https://docs.oracle.com/javase/8/docs/technotes/guides/jni/
- [CMake Android Guide]https://developer.android.com/ndk/guides/cmake

### CCGO Documentation

- [CLI Reference]../reference/cli.md
- [CCGO.toml Reference]../reference/ccgo-toml.md
- [Publishing Guide]../features/publishing.md

### Community

- [GitHub Discussions]https://github.com/zhlinh/ccgo/discussions
- [Issue Tracker]https://github.com/zhlinh/ccgo/issues

## Next Steps

- [Build System Overview]../features/build-system.md
- [Dependency Management]../features/dependency-management.md
- [iOS Development]ios.md
- [OpenHarmony Development]openharmony.md