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
아래 build/core/main.mk를 보면 환경변수 TARGET_BUILD_VARIANT에 따라서 System Property를 다르게 설정하고 있습니다.
Part 1 : /build/core/main.mk
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
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
추가로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
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)
|