꿈소년의 개발 이야기

Product 설정 파일을 통해 환경 변수 설정을 통한 선택 빌드하기 본문

Android Development

Product 설정 파일을 통해 환경 변수 설정을 통한 선택 빌드하기

꿈소년 2011. 11. 22. 17:10
반응형
출처 : http://samse.tistory.com/121#comment7314348

Product설정파일을 통해 환경변수를 설정하여 선택적으로 빌드가능
 PRODUCT_NAME : 제품명
 PRODUCT_DEVICE : 디바이스명
 PRODUCT_LOCALE : 지역정보
 PRODUCT_PACKAGE_OVERLAY : 대체될 resource가 있는 Path
 PRODUCT_PROPERTY_OVERRIDES : 추가될 system property 항목이며 /system/build.prop에 저장됨.
 PRODUCT_PACKAGES : 기본적으로 설치될 app 목록

전체 과정을 간략히 설명하면, TARGET_BUILD_VARIANT에 따라서 System Property와 설치될 모듈을 결정합니다. 그 과정을 Makefile을 따라가면서 확인해 보겠습니다.

 

시작은 open_src폴더 아래 Makefile에서 build/core/main.mk로 이동합니다.

/Makefile

### DO NOT EDIT THIS FILE ###

include build/core/main.mk

### DO NOT EDIT THIS FILE ###

 

아래 build/core/main.mk를 보면 환경변수 TARGET_BUILD_VARIANT에 따라서 System Property를 다르게 설정하고 있습니다.

Part 1 : /build/core/main.mk

## user/userdebug ##

 

user_variant := $(filter userdebug user,$(TARGET_BUILD_VARIANT))

enable_target_debugging := true

ifneq (,$(user_variant))

  # Target is secure in user builds.

  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1

 

  tags_to_install := user

  ifeq ($(user_variant),userdebug)

    # Pick up some extra useful tools

    tags_to_install += debug

  else

    # Disable debugging in plain user builds.

    enable_target_debugging :=

  endif

 

  # TODO: Always set WITH_DEXPREOPT (for user builds) once it works on OSX.

  # Also, remove the corresponding block in config/product_config.make.

  ifeq ($(HOST_OS)-$(WITH_DEXPREOPT_buildbot),linux-true)

    WITH_DEXPREOPT := true

  endif

 

  # Disallow mock locations by default for user builds

  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=0

 

else # !user_variant

  # Turn on checkjni for non-user builds.

  ADDITIONAL_BUILD_PROPERTIES += ro.kernel.android.checkjni=1

  # Set device insecure for non-user builds.

  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=0

  # Allow mock locations by default for non user builds

  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=1

endif # !user_variant

 

ifeq (true,$(strip $(enable_target_debugging)))

  # Target is more debuggable and adbd is on by default

  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=1 persist.service.adb.enable=1

  # Include the debugging/testing OTA keys in this build.

  INCLUDE_TEST_OTA_KEYS := true

else # !enable_target_debugging

  # Target is less debuggable and adbd is off by default

  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0 persist.service.adb.enable=0

endif # !enable_target_debugging

 

## eng ##

 

ifeq ($(TARGET_BUILD_VARIANT),eng)

tags_to_install := user debug eng

# Don't require the setup wizard on eng builds

#eng모드에서 ro.setupwizard.mode property를 뺍니다.

  ADDITIONAL_BUILD_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\

          $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES)))

endif

 

 

TARGET_BUILD_VARIANT에 따른 동작은 아래와 같습니다.  Android.mk의 정의된 LOCAL_MODULE_TAGS를 정의하지 않은 모듈은 기본이 user 태그입니다. 따라서 이전에 eng로 설정되어 있는 모듈들이 설치되지 않은 이유는 명시적으로 eng태그를 설정해 주었기 때문입니다.

TARGET_BUILD_VARIANT

Actions

eng

- Installs modules tagged with: eng, debug, user, and/or development.

- Installs non-APK modules that have no tags specified.

- Installs APKs according to the product definition files, in addition to tagged APKs.

- ro.secure=0

- ro.debuggable=1

- ro.kernel.android.checkjni=1

- adb is enabled by default.

user

- Installs modules tagged with user.

- Installs non-APK modules that have no tags specified.

- Installs APKs according to the product definition files; tags are ignored for APK modules.

- ro.secure=1

- ro.debuggable=0

- adb is disabled by default.

userdebug

The same as user, except:

- Also installs modules tagged with debug.

- ro.debuggable=1

- adb is enabled by default.

 

 

빌드시 build/tools/findleaves.sh를 사용해서 각 폴더의 첫번째 Android.mk파일을 모두 찾아서 Makefile에 추가합니다. 하위 폴더에 Android.mk파일이 존재하더라도 상위 폴더에 Android.mk가 존재하면 상위 폴더에 있는 Android.mk까지만 찾습니다.

그리고 현재 Product설정파일의 TARGET_DEVICE BoardConfig.mk를 포함시킵니다.

 

Part 2 : /build/core/main.mk

# Can't use first-makefiles-under here because

# --mindepth=2 makes the prunes not work.

subdir_makefiles += \

    $(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk)

 

# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)

# or under vendor/-/$(TARGET_DEVICE).  Search in both places, but

# make sure only one exists.

# Real boards should always be associated with an OEM vendor.

board_config_mk := \

    $(strip $(wildcard \

        $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \

        vendor/-/$(TARGET_DEVICE)/BoardConfig.mk \

    ))

ifeq ($(board_config_mk),)

  $(error No config file found for TARGET_DEVICE $(TARGET_DEVICE))

endif

ifneq ($(words $(board_config_mk)),1)

  $(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk))

endif

include $(board_config_mk)

TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))

board_config_mk :=

 

# Clean up/verify variables defined by the board config file.

TARGET_BOOTLOADER_BOARD_NAME := $(strip $(TARGET_BOOTLOADER_BOARD_NAME))

 

#

# Include all of the makefiles in the system

#

 

ifneq ($(ONE_SHOT_MAKEFILE),)

# We've probably been invoked by the "mm" shell function

# with a subdirectory's makefile.

include $(ONE_SHOT_MAKEFILE)

# Change CUSTOM_MODULES to include only modules that were

# defined by this makefile; this will install all of those

# modules as a side-effect.  Do this after including ONE_SHOT_MAKEFILE

# so that the modules will be installed in the same place they

# would have been with a normal make.

CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS),))

FULL_BUILD :=

INTERNAL_DEFAULT_DOCS_TARGETS :=

# Stub out the notice targets, which probably aren't defined

# when using ONE_SHOT_MAKEFILE.

NOTICE-HOST-%: ;

NOTICE-TARGET-%: ;

else

include $(subdir_makefiles)

endif

# -------------------------------------------------------------------

# All module makefiles have been included at this point.

# -------------------------------------------------------------------

 

build/tools/findleaves.sh 동작 예제

$find hardware –name “*.mk”

hardware/libhardware/Android.mk

hardware/libhardware/modules/overlay/Android.mk

hardware/libhardware_legacy/Android.mk

hardware/libhardware_legacy/flashlight/Android.mk

hardware/libhardware_legacy/gps/Android.mk

hardware/libhardware_legacy/led/Android.mk

hardware/libhardware_legacy/mount/Android.mk

hardware/libhardware_legacy/power/Android.mk

hardware/libhardware_legacy/qemu/Android.mk

hardware/libhardware_legacy/qemu_tracing/Android.mk

hardware/libhardware_legacy/tests/gpstest/Android.mk

hardware/libhardware_legacy/uevent/Android.mk

hardware/libhardware_legacy/vibrator/Android.mk

hardware/libhardware_legacy/wifi/Android.mk

hardware/ril/libril/Android.mk

hardware/ril/rild/Android.mk

hardware/ril/gpstest/Android.mk

hardware/ril/libsecril-client/Android.mk

hardware/ril/rilclient-test/Android.mk

hardware/ril/secril_multi/Android.mk

hardware/modules/sensors/Android.mk

hardware/msm7k/Android.mk

hardware/msm7k/libaudio/Android.mk

hardware/msm7k/libcamera/Android.mk

hardware/msm7k/libcopybit/Android.mk

hardware/msm7k/librpc/Android.mk

hardware/msm7k/yuv420sp2rgb/Android.mk

 

$ ./build/tools/findleaves.sh hardware Android.mk

hardware/libhardware/Android.mk => 폴더구조의 첫번째 Android.mk만 포함됨

hardware/libhardware_legacy/Android.mk

hardware/modules/sensors/Android.mk

hardware/msm7k/Android.mk

hardware/ril/gpstest/Android.mk

hardware/ril/libril/Android.mk

hardware/ril/libsecril-client/Android.mk

hardware/ril/rilclient-test/Android.mk

hardware/ril/rild/Android.mk

hardware/ril/secril_multi/Android.mk

 

hardware/msm7k/Android.mk 파일에서 아래와 같이 하위의 Android.mk파일을 상황에 따라서 include를 하여 필요한 모듈만 컴파일하여 추가시킬 때 사용할 수 있습니다. (이것을 사용해서 Samsung Open Source쪽 변경 소스 관리를 할 수 있을 것으로 보입니다. )

ifneq ($(filter capella7200, surf, $(TARGET_DEVICE)), )

  include $(all-subdir-makefiles)

endif

 

설치될 모듈들을 선택하고, LOCAL_OVERRIDES_PACKAGES로 선택된 Package를 항목에서 삭제합니다.

Part 3 : build/core/main.mk

# -------------------------------------------------------------------

# Figure out our module sets.

 

# Of the modules defined by the component makefiles,

# determine what we actually want to build.

# If a module has the "restricted" tag on it, it

# poisons the rest of the tags and shouldn't appear

# on any list.

Default_MODULES := $(sort $(ALL_DEFAULT_INSTALLED_MODULES) \

                          $(ALL_BUILT_MODULES) \

                          $(CUSTOM_MODULES))

# TODO: Remove the 3 places in the tree that use

# ALL_DEFAULT_INSTALLED_MODULES and get rid of it from this list.

 

ifdef FULL_BUILD

  # The base list of modules to build for this product is specified

  # by the appropriate product definition file, which was included

  # by product_config.make.

  user_PACKAGES := $(call module-installed-files, \

                       $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES))

  ifeq (0,1)

    $(info user packages for $(TARGET_DEVICE) ($(INTERNAL_PRODUCT)):)

    $(foreach p,$(user_PACKAGES),$(info :   $(p)))

    $(error done)

  endif

else

  # We're not doing a full build, and are probably only including

  # a subset of the module makefiles.  Don't try to build any modules

  # requested by the product, because we probably won't have rules

  # to build them.

  user_PACKAGES :=

endif

# Use tags to get the non-APPS user modules.  Use the product

# definition files to get the APPS user modules.

user_MODULES := $(sort $(call get-tagged-modules,user,_class@APPS restricted))

user_MODULES := $(user_MODULES) $(user_PACKAGES)

 

eng_MODULES := $(sort $(call get-tagged-modules,eng,restricted))

debug_MODULES := $(sort $(call get-tagged-modules,debug,restricted))

tests_MODULES := $(sort $(call get-tagged-modules,tests,restricted))

 

ifeq ($(strip $(tags_to_install)),)

$(error ASSERTION FAILED: tags_to_install should not be empty)

endif

modules_to_install := $(sort $(Default_MODULES) \

          $(foreach tag,$(tags_to_install),$($(tag)_MODULES)))

 

# Some packages may override others using LOCAL_OVERRIDES_PACKAGES.

# Filter out (do not install) any overridden packages.

overridden_packages := $(call get-package-overrides,$(modules_to_install))

ifdef overridden_packages

#  old_modules_to_install := $(modules_to_install)

  modules_to_install := \

      $(filter-out $(foreach p,$(overridden_packages),$(p) %/$(p).apk), \

          $(modules_to_install))

endif

 

추가로Android의 모든 Application은 고유한 Key를 사용해서 Signning을 수행해야 합니다. 어떤 Key Signning을 할지를 결정은 LOCAL_CERTIFICATE에 기술합니다.

packages/apps/Camera/Android.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

 

LOCAL_MODULE_TAGS := user

 

LOCAL_SRC_FILES := $(call all-java-files-under, src)

 

LOCAL_PACKAGE_NAME := Camera

LOCAL_CERTIFICATE := media

#LOCAL_CERTIFICATE := vendor/samsung/products/security/media   => 명시적으로 선택가능

 

LOCAL_STATIC_JAVA_LIBRARIES := googlelogin-client

 

#include $(BUILD_PACKAGE)

 

# Use the following include to make our test apk.

#include $(call all-makefiles-under,$(LOCAL_PATH))

 

package.mk파일을 보시면 LOCAL_CERTIFICATE가 설정되지 않으면 testkey가 사용되며, 관련 private certificate /build/target/product/security/폴더에 있는 key값을 사용합니다.

mkkey.sh   => key값을 생성하기 위한 명령어, Samsung Android폰 개발시 고유한 key를 생성해서 출시해야함.

media.pk8

media.x509.pem

platform.pk8

platform.x509.pem

shared.pk8

shared.x509.pem

testkey.pk8

testkey.x509.pem

 

/build/core/package.mk

# Pick a key to sign the package with.  If this package hasn't specified

# an explicit certificate, use the default.

# Secure release builds will have their packages signed after the fact,

# so it's ok for these private keys to be in the clear.

ifeq ($(LOCAL_CERTIFICATE),)

    LOCAL_CERTIFICATE := testkey

endif

# If this is not an absolute certificate, assign it to a generic one.

ifeq ($(dir $(strip $(LOCAL_CERTIFICATE))),./)

    LOCAL_CERTIFICATE := $(SRC_TARGET_DIR)/product/security/$(LOCAL_CERTIFICATE)

endif

private_key := $(LOCAL_CERTIFICATE).pk8

certificate := $(LOCAL_CERTIFICATE).x509.pem

 

$(LOCAL_BUILT_MODULE): $(private_key) $(certificate) $(SIGNAPK_JAR)

$(LOCAL_BUILT_MODULE): PRIVATE_PRIVATE_KEY := $(private_key)

$(LOCAL_BUILT_MODULE): PRIVATE_CERTIFICATE := $(certificate)

 

PACKAGES.$(LOCAL_PACKAGE_NAME).PRIVATE_KEY := $(private_key)

PACKAGES.$(LOCAL_PACKAGE_NAME).CERTIFICATE := $(certificate)

 

# Define the rule to build the actual package.

$(LOCAL_BUILT_MODULE): $(AAPT) | $(ZIPALIGN)

$(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries)

$(LOCAL_BUILT_MODULE): $(all_res_assets) $(jni_shared_libraries) $(full_android_manifest)

    @echo "target Package: $(PRIVATE_MODULE) ($@)"

    $(create-empty-package)

    $(add-assets-to-package)

ifneq ($(jni_shared_libraries),)

    $(add-jni-shared-libs-to-package)

endif

ifneq ($(full_classes_jar),)

    $(add-dex-to-package)

endif

    $(sign-package)

    @# Alignment must happen after all other zip operations.

    $(align-package)

 

# Save information about this package

PACKAGES.$(LOCAL_PACKAGE_NAME).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))

PACKAGES.$(LOCAL_PACKAGE_NAME).RESOURCE_FILES := $(all_resources)

 

PACKAGES := $(PACKAGES) $(LOCAL_PACKAGE_NAME)