Как включить существующий файл с Android NDK

Поэтому у меня есть огромный существующий проект C, который я разместил в каталоге $PROJECT/jni . Этот проект обычно создается путем запуска скрипта configure, который создает Makefile, который затем позволяет скомпилировать проект с помощью make .

Этот проект довольно большой и содержит много каталогов, содержащих исходные файлы и файлы заголовков.

Думаю, мне не хватает фундаментального понимания того, как Android.mk должен работать. Предполагается ли заменить файл конфигурации и makefile, который в настоящее время используется для компиляции проекта? Или я бы включил сгенерированный make-файл из моего скрипта configure в Android.mk ? Примеры, которые они предоставляют, довольно тривиальны только с несколькими исходными файлами. Мой каталог jni больше похож:

 jni/ folder1/subfolder1 folder1/subfolder2 folder1/source folder2/source ..... foldern/source configure/ configure/configure.sh Makefile Android.mk 

Сгенерированные make-файлы довольно обширны (хорошая конфигурация и есть один в каждом каталоге), поэтому я немного потерял, как подойти к этому.

РЕДАКТИРОВАТЬ:

Основная проблема заключается в том, что примеры, которые поставляются с NDK, являются тривиальными примерами. У них есть 3-5 исходных файлов в каталоге jni верхнего уровня. Моя проблема в том, что это огромный проект со сложной конфигурацией с 4 папками верхнего уровня, каждый со многими подкаталогами. Я не могу просто переместить источник в jni-папку и запустить компилятор ndk.

Solutions Collecting From Web of "Как включить существующий файл с Android NDK"

Чтобы ответить на ваш вопрос, да, Android.mk это система Android для Android. Google едва упоминает, что «язык» этого файла реализован как макросы GNU make. Документы хотят, чтобы вы описали свой проект с точки зрения этих макросов. Они справляются со всеми деталями кросс-компиляции. Я уверен, что Google предпринял такой подход, чтобы улучшить переносимость файлов Android.mk мере развития инструментов разработки.

Результат заключается в том, что (и я знаю, что вы не захотите это услышать) лучший ответ – это, вероятно, написать правильный NDK Android.mk для вашего большого проекта с нуля.

В этой статье изложены те же наблюдения, которые я сделал, портируя библиотеку около 800 файлов и 300 КБ SLOC. К сожалению, я сжег почти две недели, достигнув такого же вывода: кросс-компиляция приводит к сбою хотя бы некоторых скриптов configure (приводят к ошибочным файлам config.h ). Я «изобрел» почти те же самые методы, которые он использует в статье. Но даже после того, как я получил чистую сборку, полученная статическая библиотека не работала полностью. Время отладки нет полезной информации. [Предостережение: я не специалист по настройкам. Гуру, вероятно, заметила бы мою ошибку. Так оно и есть.] Мне понадобилось пару дней, чтобы создать чистый Android.mk . Полученная библиотека провела все тесты в первый раз. И он портировал чисто через несколько оборотов инструментов разработки.

К сожалению, создание библиотеки, использующей configure без использования автоматических инструментов, означает создание собственного config.h вручную для целевой среды. Это может быть не так плохо, как кажется. Системы IME имеют тенденцию определять гораздо больше в своих configure средах, чем они на самом деле используют. Получение четкого представления о реальных зависимостях может погасить утомительные усилия во время будущего рефакторинга.

В сводном заявлении из статьи говорится все:

Autotool хорош только в системах GNU, и использование его для кросс-компиляции может быть действительно утомительным, запутанным, подверженным ошибкам или даже невозможным. Метод, описанный здесь, является взломом и должен использоваться на свой страх и риск.

Извините, у меня нет более позитивного предложения.

Мой ответ лучше всего работает в тандеме с ответом Джина .

./configure создание файла конфигурации основано на компиляции (и, возможно, запуске) небольших фрагментов кода C для каждого теста. Тестирование только для компиляции может быть успешно протестировано в среде кросс-компиляции. Тем не менее, тесты компиляции и запуска невозможно выполнить в среде кросс-компиляции. Успех каждого теста устанавливает соответствующую переменную в шаблоне config.h.in для создания config.h .

Таким образом, чтобы начать процесс преобразования, вам нужно будет установить CPP , CC , LD и другие инструменты в набор инструментов кросс-компилятора (возможно, из NDK ), а затем запустите ./configure . Как только это будет сделано, вам нужно исправить config.h чтобы он соответствовал вашей целевой среде. Это ваш самый важный и наиболее подверженный ошибкам шаг.

Что касается Android.mk , он следует за форматом, близким к Makefile.am который можно легко преобразовать в него. Вы можете игнорировать Makefile.in и Makefile , поскольку они создаются из Makefile.am .

Чтобы взять пример файла (версия 5.11), я запустил configure со следующими параметрами,

 ./configure --host arm-toshiba-linux-androideabi --build x86_64-linux-gnu \ --prefix=/data/local/ host_alias=arm-linux-androideabi \ "CFLAGS=--sysroot=~/ndk/platforms/android-8/arch-arm -Wall -Wextra" \ "CPPFLAGS=--sysroot=~/ndk/platforms/android-8/arch-arm" \ CPP=arm-linux-androideabi-cpp 

Следующим шагом было взять src/Makefile.am как src/Makefile.am ниже:

 MAGIC = $(pkgdatadir)/magic lib_LTLIBRARIES = libmagic.la include_HEADERS = magic.h bin_PROGRAMS = file AM_CPPFLAGS = -DMAGIC='"$(MAGIC)"' AM_CFLAGS = $(CFLAG_VISIBILITY) @WARNINGS@ libmagic_la_SOURCES = magic.c apprentice.c softmagic.c ascmagic.c \ encoding.c compress.c is_tar.c readelf.c print.c fsmagic.c \ funcs.c file.h readelf.h tar.h apptype.c \ file_opts.h elfclass.h mygetopt.h cdf.c cdf_time.c readcdf.c cdf.h libmagic_la_LDFLAGS = -no-undefined -version-info 1:0:0 if MINGW MINGWLIBS = -lgnurx -lshlwapi else MINGWLIBS = endif libmagic_la_LIBADD = $(LTLIBOBJS) $(MINGWLIBS) file_SOURCES = file.c file_LDADD = libmagic.la CLEANFILES = magic.h EXTRA_DIST = magic.h.in HDR= $(top_srcdir)/src/magic.h.in BUILT_SOURCES = magic.h magic.h: ${HDR} sed -e "s/X.YY/$$(echo @VERSION@ | tr -d .)/" < ${HDR} > $@ 

И создайте Android.mk .

Последним и самым важным шагом было изменение config.h чтобы точно отразить состояние целевой системы. Это будет ручной процесс, который я не могу дать обходным путем, в основном, заглядывая в configure.log, просматривая заголовки и «вызывая» Google. Плоды этого труда доступны на XDA .

Вот решение для того, чтобы делать вещи по-другому: создание как внешней библиотеки, так и пакета Android из стандартных Make-файлов.

В качестве предварительного условия вам необходимо установить все необходимое для разработки в командной строке Android:

  • Отдельная инструментальная цепочка, см. Документацию, включенную в Android NDK;
  • муравей.

Структура примера: каталог для внешней библиотеки и каталог для источников Android на одном уровне с Makefile в каждом каталоге и рекурсивный Makefile верхнего уровня:

 Makefile mylib/ Makefile android/ Makefile 

mylib/Makefile создает статическую библиотеку:

 AR=/path/to/standalone/bin/arm-linux-androideabi-ar CC=/path/to/standalone/bin/arm-linux-androideabi-gcc libmylib.a: mylib.o $(AR) rcs libmylib.a mylib.o mylib.o: mylib.c $(CC) -c mylib.c -o mylib.o 

android/Makefile предоставляет правила для сборки пакета Android:

  • Нам нужна зависимость для копирования mylib когда он изменен;
  • Мы используем файл jni/ndkmake.c чтобы обернуть вызовы mylib и предоставить конкретную информацию для Android;
  • Пакет android зависит от источников Java и от общей библиотеки.

Makefile предоставляет две цели: release (по умолчанию) и debug для создания пакета выпуска или отладочного.

 NDK_BUILD=/path/to/ndk-build JAVASRC=src/com/example/ndkmake/NdkMake.java release: bin/NdkMake-release-unsigned.apk debug: bin/NdkMake-debug.apk bin/NdkMake-release-unsigned.apk: libs/armeabi/libndkmake.so $(JAVASRC) ant release bin/NdkMake-debug.apk: libs/armeabi/libndkmake.so $(JAVASRC) ant debug libs/armeabi/libndkmake.so: jni/ndkmake.c jni/libmylib.a $(NDK_BUILD) jni/libmylib.a: ../mylib/libmylib.a cp ../mylib/libmylib.a jni/libmylib.a 

Файл Android.mk предоставляет правила для включения статической библиотеки в сборку в качестве готовой. Мы LOCAL_EXPORT_C_INCLUDES заголовки из библиотеки mylib используя LOCAL_EXPORT_C_INCLUDES .

 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := ndkmake LOCAL_SRC_FILES := ndkmake.c LOCAL_STATIC_LIBRARIES := mylib-prebuilt include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := mylib-prebuilt LOCAL_SRC_FILES := libmylib.a LOCAL_EXPORT_C_INCLUDES := ../mylib/ include $(PREBUILT_STATIC_LIBRARY) 

Теперь нам нужен только Makefile верхнего уровня для создания двух подкаталогов:

 all: libmylib package libmylib: cd mylib && $(MAKE) package: cd android && $(MAKE) 

Любые изменения в библиотеке, источниках jni или источниках Java вызовут перестройку пакета.