parent
61536d4497
commit
3952f6cb0d
@ -0,0 +1,13 @@
|
||||
ifeq ($(BOARD_USES_MTK_HARDWARE),true)
|
||||
mtk_flags := -DMTK_HARDWARE
|
||||
|
||||
TARGET_GLOBAL_CFLAGS += $(mtk_flags)
|
||||
TARGET_GLOBAL_CPPFLAGS += $(mtk_flags)
|
||||
CLANG_TARGET_GLOBAL_CFLAGS += $(mtk_flags)
|
||||
CLANG_TARGET_GLOBAL_CPPFLAGS += $(mtk_flags)
|
||||
|
||||
2ND_TARGET_GLOBAL_CFLAGS += $(mtk_flags)
|
||||
2ND_TARGET_GLOBAL_CPPFLAGS += $(mtk_flags)
|
||||
2ND_CLANG_TARGET_GLOBAL_CFLAGS += $(mtk_flags)
|
||||
2ND_CLANG_TARGET_GLOBAL_CPPFLAGS += $(mtk_flags)
|
||||
endif
|
@ -0,0 +1,5 @@
|
||||
# Board platforms lists to be used for
|
||||
# TARGET_BOARD_PLATFORM specific featurization
|
||||
MTK_BOARD_PLATFORMS := mt6592
|
||||
MTK_BOARD_PLATFORMS += mt6582
|
||||
MTK_BOARD_PLATFORMS += mt6572
|
@ -0,0 +1,133 @@
|
||||
# Target-specific configuration
|
||||
|
||||
# Populate the qcom hardware variants in the project pathmap.
|
||||
define ril-set-path-variant
|
||||
$(call project-set-path-variant,ril,TARGET_RIL_VARIANT,hardware/$(1))
|
||||
endef
|
||||
define wlan-set-path-variant
|
||||
$(call project-set-path-variant,wlan,TARGET_WLAN_VARIANT,hardware/qcom/$(1))
|
||||
endef
|
||||
define bt-vendor-set-path-variant
|
||||
$(call project-set-path-variant,bt-vendor,TARGET_BT_VENDOR_VARIANT,hardware/qcom/$(1))
|
||||
endef
|
||||
|
||||
# Set device-specific HALs into project pathmap
|
||||
define set-device-specific-path
|
||||
$(if $(USE_DEVICE_SPECIFIC_$(1)), \
|
||||
$(if $(DEVICE_SPECIFIC_$(1)_PATH), \
|
||||
$(eval path := $(DEVICE_SPECIFIC_$(1)_PATH)), \
|
||||
$(eval path := $(TARGET_DEVICE_DIR)/$(2))), \
|
||||
$(eval path := $(3))) \
|
||||
$(call project-set-path,qcom-$(2),$(strip $(path)))
|
||||
endef
|
||||
|
||||
ifeq ($(BOARD_USES_QCOM_HARDWARE),true)
|
||||
|
||||
qcom_flags := -DQCOM_HARDWARE
|
||||
qcom_flags += -DQCOM_BSP
|
||||
qcom_flags += -DQTI_BSP
|
||||
|
||||
TARGET_USES_QCOM_BSP := true
|
||||
|
||||
# Tell HALs that we're compiling an AOSP build with an in-line kernel
|
||||
TARGET_COMPILE_WITH_MSM_KERNEL := true
|
||||
|
||||
ifneq ($(filter msm7x27a msm7x30 msm8660 msm8960,$(TARGET_BOARD_PLATFORM)),)
|
||||
# Enable legacy graphics functions
|
||||
qcom_flags += -DQCOM_BSP_LEGACY
|
||||
# Enable legacy audio functions
|
||||
ifeq ($(BOARD_USES_LEGACY_ALSA_AUDIO),true)
|
||||
USE_CUSTOM_AUDIO_POLICY := 1
|
||||
qcom_flags += -DLEGACY_ALSA_AUDIO
|
||||
endif
|
||||
endif
|
||||
|
||||
# Enable extra offloading for post-805 targets
|
||||
ifneq ($(filter msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),)
|
||||
qcom_flags += -DHAS_EXTRA_FLAC_METADATA
|
||||
endif
|
||||
|
||||
TARGET_GLOBAL_CFLAGS += $(qcom_flags)
|
||||
TARGET_GLOBAL_CPPFLAGS += $(qcom_flags)
|
||||
CLANG_TARGET_GLOBAL_CFLAGS += $(qcom_flags)
|
||||
CLANG_TARGET_GLOBAL_CPPFLAGS += $(qcom_flags)
|
||||
|
||||
# Multiarch needs these too..
|
||||
2ND_TARGET_GLOBAL_CFLAGS += $(qcom_flags)
|
||||
2ND_TARGET_GLOBAL_CPPFLAGS += $(qcom_flags)
|
||||
2ND_CLANG_TARGET_GLOBAL_CFLAGS += $(qcom_flags)
|
||||
2ND_CLANG_TARGET_GLOBAL_CPPFLAGS += $(qcom_flags)
|
||||
|
||||
ifeq ($(QCOM_HARDWARE_VARIANT),)
|
||||
ifneq ($(filter msm8610 msm8226 msm8974,$(TARGET_BOARD_PLATFORM)),)
|
||||
QCOM_HARDWARE_VARIANT := msm8974
|
||||
else
|
||||
ifneq ($(filter msm8909 msm8916,$(TARGET_BOARD_PLATFORM)),)
|
||||
QCOM_HARDWARE_VARIANT := msm8916
|
||||
else
|
||||
ifneq ($(filter msm8953 msm8937,$(TARGET_BOARD_PLATFORM)),)
|
||||
QCOM_HARDWARE_VARIANT := msm8937
|
||||
else
|
||||
ifneq ($(filter msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),)
|
||||
QCOM_HARDWARE_VARIANT := msm8994
|
||||
else
|
||||
QCOM_HARDWARE_VARIANT := $(TARGET_BOARD_PLATFORM)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# HACK: check to see if build uses standard QC HAL paths by checking for CM path structure
|
||||
AOSP_VARIANT_MAKEFILE := $(wildcard hardware/qcom/audio/default/Android.mk)
|
||||
ifeq ("$(AOSP_VARIANT_MAKEFILE)","")
|
||||
$(call project-set-path,qcom-audio,hardware/qcom/audio)
|
||||
$(call project-set-path,qcom-display,hardware/qcom/display)
|
||||
$(call project-set-path,qcom-media,hardware/qcom/media)
|
||||
$(call set-device-specific-path,CAMERA,camera,hardware/qcom/camera)
|
||||
$(call set-device-specific-path,GPS,gps,hardware/qcom/gps)
|
||||
$(call set-device-specific-path,SENSORS,sensors,hardware/qcom/sensors)
|
||||
$(call set-device-specific-path,LOC_API,loc-api,vendor/qcom/opensource/location)
|
||||
$(call set-device-specific-path,DATASERVICES,dataservices,vendor/qcom/opensource/dataservices)
|
||||
$(call project-set-path,ril,hardware/ril)
|
||||
$(call project-set-path,wlan,hardware/qcom/wlan)
|
||||
$(call project-set-path,bt-vendor,hardware/qcom/bt)
|
||||
else
|
||||
$(call project-set-path,qcom-audio,hardware/qcom/audio-caf/$(QCOM_HARDWARE_VARIANT))
|
||||
|
||||
ifeq ($(SONY_BF64_KERNEL_VARIANT),true)
|
||||
$(call project-set-path,qcom-display,hardware/qcom/display-caf/sony)
|
||||
$(call project-set-path,qcom-media,hardware/qcom/media-caf/sony)
|
||||
else
|
||||
$(call project-set-path,qcom-display,hardware/qcom/display-caf/$(QCOM_HARDWARE_VARIANT))
|
||||
$(call project-set-path,qcom-media,hardware/qcom/media-caf/$(QCOM_HARDWARE_VARIANT))
|
||||
endif
|
||||
|
||||
$(call set-device-specific-path,CAMERA,camera,hardware/qcom/camera)
|
||||
$(call set-device-specific-path,GPS,gps,hardware/qcom/gps)
|
||||
$(call set-device-specific-path,SENSORS,sensors,hardware/qcom/sensors)
|
||||
$(call set-device-specific-path,LOC_API,loc-api,vendor/qcom/opensource/location)
|
||||
$(call set-device-specific-path,DATASERVICES,dataservices,vendor/qcom/opensource/dataservices)
|
||||
|
||||
$(call ril-set-path-variant,ril)
|
||||
$(call wlan-set-path-variant,wlan-caf)
|
||||
$(call bt-vendor-set-path-variant,bt-caf)
|
||||
endif # AOSP_VARIANT_MAKEFILE
|
||||
|
||||
else
|
||||
|
||||
$(call project-set-path,qcom-audio,hardware/qcom/audio/default)
|
||||
$(call project-set-path,qcom-display,hardware/qcom/display/$(TARGET_BOARD_PLATFORM))
|
||||
$(call project-set-path,qcom-media,hardware/qcom/media)
|
||||
|
||||
$(call project-set-path,qcom-camera,hardware/qcom/camera)
|
||||
$(call project-set-path,qcom-gps,hardware/qcom/gps)
|
||||
$(call project-set-path,qcom-sensors,hardware/qcom/sensors)
|
||||
$(call project-set-path,qcom-loc-api,vendor/qcom/opensource/location)
|
||||
$(call project-set-path,qcom-dataservices,$(TARGET_DEVICE_DIR)/dataservices)
|
||||
|
||||
$(call ril-set-path-variant,ril)
|
||||
$(call wlan-set-path-variant,wlan)
|
||||
$(call bt-vendor-set-path-variant,bt)
|
||||
|
||||
endif
|
@ -0,0 +1,230 @@
|
||||
# Board platforms lists to be used for
|
||||
# TARGET_BOARD_PLATFORM specific featurization
|
||||
QCOM_BOARD_PLATFORMS += msm7x27a
|
||||
QCOM_BOARD_PLATFORMS += msm7x30
|
||||
QCOM_BOARD_PLATFORMS += msm8226
|
||||
QCOM_BOARD_PLATFORMS += msm8610
|
||||
QCOM_BOARD_PLATFORMS += msm8660
|
||||
QCOM_BOARD_PLATFORMS += msm8909
|
||||
QCOM_BOARD_PLATFORMS += msm8916
|
||||
QCOM_BOARD_PLATFORMS += msm8960
|
||||
QCOM_BOARD_PLATFORMS += msm8974
|
||||
QCOM_BOARD_PLATFORMS += mpq8092
|
||||
QCOM_BOARD_PLATFORMS += msm8937
|
||||
QCOM_BOARD_PLATFORMS += msm8952
|
||||
QCOM_BOARD_PLATFORMS += msm8953
|
||||
QCOM_BOARD_PLATFORMS += msm8992
|
||||
QCOM_BOARD_PLATFORMS += msm8994
|
||||
QCOM_BOARD_PLATFORMS += msm8996
|
||||
QCOM_BOARD_PLATFORMS += msm_bronze
|
||||
QCOM_BOARD_PLATFORMS += apq8084
|
||||
|
||||
MSM7K_BOARD_PLATFORMS := msm7x30
|
||||
MSM7K_BOARD_PLATFORMS += msm7x27
|
||||
MSM7K_BOARD_PLATFORMS += msm7x27a
|
||||
MSM7K_BOARD_PLATFORMS += msm7k
|
||||
|
||||
QSD8K_BOARD_PLATFORMS := qsd8k
|
||||
|
||||
|
||||
# vars for use by utils
|
||||
empty :=
|
||||
space := $(empty) $(empty)
|
||||
colon := $(empty):$(empty)
|
||||
underscore := $(empty)_$(empty)
|
||||
|
||||
# $(call match-word,w1,w2)
|
||||
# checks if w1 == w2
|
||||
# How it works
|
||||
# if (w1-w2 not empty or w2-w1 not empty) then not_match else match
|
||||
#
|
||||
# returns true or empty
|
||||
#$(warning :$(1): :$(2): :$(subst $(1),,$(2)):) \
|
||||
#$(warning :$(2): :$(1): :$(subst $(2),,$(1)):) \
|
||||
#
|
||||
define match-word
|
||||
$(strip \
|
||||
$(if $(or $(subst $(1),$(empty),$(2)),$(subst $(2),$(empty),$(1))),,true) \
|
||||
)
|
||||
endef
|
||||
|
||||
# $(call find-word-in-list,w,wlist)
|
||||
# finds an exact match of word w in word list wlist
|
||||
#
|
||||
# How it works
|
||||
# fill wlist spaces with colon
|
||||
# wrap w with colon
|
||||
# search word w in list wl, if found match m, return stripped word w
|
||||
#
|
||||
# returns stripped word or empty
|
||||
define find-word-in-list
|
||||
$(strip \
|
||||
$(eval wl:= $(colon)$(subst $(space),$(colon),$(strip $(2)))$(colon)) \
|
||||
$(eval w:= $(colon)$(strip $(1))$(colon)) \
|
||||
$(eval m:= $(findstring $(w),$(wl))) \
|
||||
$(if $(m),$(1),) \
|
||||
)
|
||||
endef
|
||||
|
||||
# $(call match-word-in-list,w,wlist)
|
||||
# does an exact match of word w in word list wlist
|
||||
# How it works
|
||||
# if the input word is not empty
|
||||
# return output of an exact match of word w in wordlist wlist
|
||||
# else
|
||||
# return empty
|
||||
# returns true or empty
|
||||
define match-word-in-list
|
||||
$(strip \
|
||||
$(if $(strip $(1)), \
|
||||
$(call match-word,$(call find-word-in-list,$(1),$(2)),$(strip $(1))), \
|
||||
) \
|
||||
)
|
||||
endef
|
||||
|
||||
# $(call match-prefix,p,delim,w/wlist)
|
||||
# matches prefix p in wlist using delimiter delim
|
||||
#
|
||||
# How it works
|
||||
# trim the words in wlist w
|
||||
# if find-word-in-list returns not empty
|
||||
# return true
|
||||
# else
|
||||
# return empty
|
||||
#
|
||||
define match-prefix
|
||||
$(strip \
|
||||
$(eval w := $(strip $(1)$(strip $(2)))) \
|
||||
$(eval text := $(patsubst $(w)%,$(1),$(3))) \
|
||||
$(if $(call match-word-in-list,$(1),$(text)),true,) \
|
||||
)
|
||||
endef
|
||||
|
||||
# ----
|
||||
# The following utilities are meant for board platform specific
|
||||
# featurisation
|
||||
|
||||
# $(call get-vendor-board-platforms,v)
|
||||
# returns list of board platforms for vendor v
|
||||
define get-vendor-board-platforms
|
||||
$(if $(call match-word,$(BOARD_USES_$(1)_HARDWARE),true),$($(1)_BOARD_PLATFORMS))
|
||||
endef
|
||||
|
||||
# $(call is-board-platform,bp)
|
||||
# returns true or empty
|
||||
define is-board-platform
|
||||
$(call match-word,$(1),$(TARGET_BOARD_PLATFORM))
|
||||
endef
|
||||
|
||||
# $(call is-not-board-platform,bp)
|
||||
# returns true or empty
|
||||
define is-not-board-platform
|
||||
$(if $(call match-word,$(1),$(TARGET_BOARD_PLATFORM)),,true)
|
||||
endef
|
||||
|
||||
# $(call is-board-platform-in-list,bpl)
|
||||
# returns true or empty
|
||||
define is-board-platform-in-list
|
||||
$(call match-word-in-list,$(TARGET_BOARD_PLATFORM),$(1))
|
||||
endef
|
||||
|
||||
# $(call is-vendor-board-platform,vendor)
|
||||
# returns true or empty
|
||||
define is-vendor-board-platform
|
||||
$(strip \
|
||||
$(call match-word-in-list,$(TARGET_BOARD_PLATFORM),\
|
||||
$(call get-vendor-board-platforms,$(1)) \
|
||||
) \
|
||||
)
|
||||
endef
|
||||
|
||||
# $(call is-chipset-in-board-platform,chipset)
|
||||
# does a prefix match of chipset in TARGET_BOARD_PLATFORM
|
||||
# uses underscore as a delimiter
|
||||
#
|
||||
# returns true or empty
|
||||
define is-chipset-in-board-platform
|
||||
$(call match-prefix,$(1),$(underscore),$(TARGET_BOARD_PLATFORM))
|
||||
endef
|
||||
|
||||
# $(call is-chipset-prefix-in-board-platform,prefix)
|
||||
# does a chipset prefix match in TARGET_BOARD_PLATFORM
|
||||
# assumes '_' and 'a' as the delimiter to the chipset prefix
|
||||
#
|
||||
# How it works
|
||||
# if ($(prefix)_ or $(prefix)a match in board platform)
|
||||
# return true
|
||||
# else
|
||||
# return empty
|
||||
#
|
||||
define is-chipset-prefix-in-board-platform
|
||||
$(strip \
|
||||
$(eval delim_a := $(empty)a$(empty)) \
|
||||
$(if \
|
||||
$(or \
|
||||
$(call match-prefix,$(1),$(delim_a),$(TARGET_BOARD_PLATFORM)), \
|
||||
$(call match-prefix,$(1),$(underscore),$(TARGET_BOARD_PLATFORM)), \
|
||||
), \
|
||||
true, \
|
||||
) \
|
||||
)
|
||||
endef
|
||||
|
||||
#----
|
||||
# The following utilities are meant for Android Code Name
|
||||
# specific featurisation
|
||||
#
|
||||
# refer http://source.android.com/source/build-numbers.html
|
||||
# for code names and associated sdk versions
|
||||
CUPCAKE_SDK_VERSIONS := 3
|
||||
DONUT_SDK_VERSIONS := 4
|
||||
ECLAIR_SDK_VERSIONS := 5 6 7
|
||||
FROYO_SDK_VERSIONS := 8
|
||||
GINGERBREAD_SDK_VERSIONS := 9 10
|
||||
HONEYCOMB_SDK_VERSIONS := 11 12 13
|
||||
ICECREAM_SANDWICH_SDK_VERSIONS := 14 15
|
||||
JELLY_BEAN_SDK_VERSIONS := 16 17 18
|
||||
|
||||
# $(call is-platform-sdk-version-at-least,version)
|
||||
# version is a numeric SDK_VERSION defined above
|
||||
define is-platform-sdk-version-at-least
|
||||
$(strip \
|
||||
$(if $(filter 1,$(shell echo "$$(( $(PLATFORM_SDK_VERSION) >= $(1) ))" )), \
|
||||
true, \
|
||||
) \
|
||||
)
|
||||
endef
|
||||
|
||||
# $(call is-android-codename,codename)
|
||||
# codename is one of cupcake,donut,eclair,froyo,gingerbread,icecream
|
||||
# please refer the $(codename)_SDK_VERSIONS declared above
|
||||
define is-android-codename
|
||||
$(strip \
|
||||
$(if \
|
||||
$(call match-word-in-list,$(PLATFORM_SDK_VERSION),$($(1)_SDK_VERSIONS)), \
|
||||
true, \
|
||||
) \
|
||||
)
|
||||
endef
|
||||
|
||||
# $(call is-android-codename-in-list,cnlist)
|
||||
# cnlist is combination/list of android codenames
|
||||
define is-android-codename-in-list
|
||||
$(strip \
|
||||
$(eval acn := $(empty)) \
|
||||
$(foreach \
|
||||
i,$(1),\
|
||||
$(eval acn += \
|
||||
$(if \
|
||||
$(call \
|
||||
match-word-in-list,\
|
||||
$(PLATFORM_SDK_VERSION),\
|
||||
$($(i)_SDK_VERSIONS)\
|
||||
),\
|
||||
true,\
|
||||
)\
|
||||
)\
|
||||
) \
|
||||
$(if $(strip $(acn)),true,) \
|
||||
)
|
||||
endef
|
@ -0,0 +1,931 @@
|
||||
function __print_cm_functions_help() {
|
||||
cat <<EOF
|
||||
Additional CyanogenMod functions:
|
||||
- cout: Changes directory to out.
|
||||
- mmp: Builds all of the modules in the current directory and pushes them to the device.
|
||||
- mmap: Builds all of the modules in the current directory and its dependencies, then pushes the package to the device.
|
||||
- mmmp: Builds all of the modules in the supplied directories and pushes them to the device.
|
||||
- mms: Short circuit builder. Quickly re-build the kernel, rootfs, boot and system images
|
||||
without deep dependencies. Requires the full build to have run before.
|
||||
- cmgerrit: A Git wrapper that fetches/pushes patch from/to CM Gerrit Review.
|
||||
- cmrebase: Rebase a Gerrit change and push it again.
|
||||
- cmremote: Add git remote for CM Gerrit Review.
|
||||
- aospremote: Add git remote for matching AOSP repository.
|
||||
- cafremote: Add git remote for matching CodeAurora repository.
|
||||
- mka: Builds using SCHED_BATCH on all processors.
|
||||
- mkap: Builds the module(s) using mka and pushes them to the device.
|
||||
- cmka: Cleans and builds using mka.
|
||||
- repodiff: Diff 2 different branches or tags within the same repo
|
||||
- repolastsync: Prints date and time of last repo sync.
|
||||
- reposync: Parallel repo sync using ionice and SCHED_BATCH.
|
||||
- repopick: Utility to fetch changes from Gerrit.
|
||||
- installboot: Installs a boot.img to the connected device.
|
||||
- installrecovery: Installs a recovery.img to the connected device.
|
||||
EOF
|
||||
}
|
||||
|
||||
function brunch()
|
||||
{
|
||||
breakfast $*
|
||||
if [ $? -eq 0 ]; then
|
||||
mka bacon
|
||||
else
|
||||
echo "No such item in brunch menu. Try 'breakfast'"
|
||||
return 1
|
||||
fi
|
||||
return $?
|
||||
}
|
||||
|
||||
function breakfast()
|
||||
{
|
||||
target=$1
|
||||
local variant=$2
|
||||
CM_DEVICES_ONLY="true"
|
||||
unset LUNCH_MENU_CHOICES
|
||||
add_lunch_combo full-eng
|
||||
for f in `/bin/ls vendor/cm/vendorsetup.sh 2> /dev/null`
|
||||
do
|
||||
echo "including $f"
|
||||
. $f
|
||||
done
|
||||
unset f
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
# No arguments, so let's have the full menu
|
||||
lunch
|
||||
else
|
||||
echo "z$target" | grep -q "-"
|
||||
if [ $? -eq 0 ]; then
|
||||
# A buildtype was specified, assume a full device name
|
||||
lunch $target
|
||||
else
|
||||
# This is probably just the CM model name
|
||||
if [ -z "$variant" ]; then
|
||||
variant="userdebug"
|
||||
fi
|
||||
lunch cm_$target-$variant
|
||||
fi
|
||||
fi
|
||||
return $?
|
||||
}
|
||||
|
||||
alias bib=breakfast
|
||||
|
||||
function eat()
|
||||
{
|
||||
if [ "$OUT" ] ; then
|
||||
MODVERSION=$(get_build_var CM_VERSION)
|
||||
ZIPFILE=cm-$MODVERSION.zip
|
||||
ZIPPATH=$OUT/$ZIPFILE
|
||||
if [ ! -f $ZIPPATH ] ; then
|
||||
echo "Nothing to eat"
|
||||
return 1
|
||||
fi
|
||||
adb start-server # Prevent unexpected starting server message from adb get-state in the next line
|
||||
if [ $(adb get-state) != device -a $(adb shell test -e /sbin/recovery 2> /dev/null; echo $?) != 0 ] ; then
|
||||
echo "No device is online. Waiting for one..."
|
||||
echo "Please connect USB and/or enable USB debugging"
|
||||
until [ $(adb get-state) = device -o $(adb shell test -e /sbin/recovery 2> /dev/null; echo $?) = 0 ];do
|
||||
sleep 1
|
||||
done
|
||||
echo "Device Found.."
|
||||
fi
|
||||
if (adb shell getprop ro.cm.device | grep -q "$CM_BUILD");
|
||||
then
|
||||
# if adbd isn't root we can't write to /cache/recovery/
|
||||
adb root
|
||||
sleep 1
|
||||
adb wait-for-device
|
||||
cat << EOF > /tmp/command
|
||||
--sideload_auto_reboot
|
||||
EOF
|
||||
if adb push /tmp/command /cache/recovery/ ; then
|
||||
echo "Rebooting into recovery for sideload installation"
|
||||
adb reboot recovery
|
||||
adb wait-for-sideload
|
||||
adb sideload $ZIPPATH
|
||||
fi
|
||||
rm /tmp/command
|
||||
else
|
||||
echo "Nothing to eat"
|
||||
return 1
|
||||
fi
|
||||
return $?
|
||||
else
|
||||
echo "The connected device does not appear to be $CM_BUILD, run away!"
|
||||
fi
|
||||
}
|
||||
|
||||
function omnom()
|
||||
{
|
||||
brunch $*
|
||||
eat
|
||||
}
|
||||
|
||||
function cout()
|
||||
{
|
||||
if [ "$OUT" ]; then
|
||||
cd $OUT
|
||||
else
|
||||
echo "Couldn't locate out directory. Try setting OUT."
|
||||
fi
|
||||
}
|
||||
|
||||
function dddclient()
|
||||
{
|
||||
local OUT_ROOT=$(get_abs_build_var PRODUCT_OUT)
|
||||
local OUT_SYMBOLS=$(get_abs_build_var TARGET_OUT_UNSTRIPPED)
|
||||
local OUT_SO_SYMBOLS=$(get_abs_build_var TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED)
|
||||
local OUT_VENDOR_SO_SYMBOLS=$(get_abs_build_var TARGET_OUT_VENDOR_SHARED_LIBRARIES_UNSTRIPPED)
|
||||
local OUT_EXE_SYMBOLS=$(get_symbols_directory)
|
||||
local PREBUILTS=$(get_abs_build_var ANDROID_PREBUILTS)
|
||||
local ARCH=$(get_build_var TARGET_ARCH)
|
||||
local GDB
|
||||
case "$ARCH" in
|
||||
arm) GDB=arm-linux-androideabi-gdb;;
|
||||
arm64) GDB=arm-linux-androideabi-gdb; GDB64=aarch64-linux-android-gdb;;
|
||||
mips|mips64) GDB=mips64el-linux-android-gdb;;
|
||||
x86) GDB=x86_64-linux-android-gdb;;
|
||||
x86_64) GDB=x86_64-linux-android-gdb;;
|
||||
*) echo "Unknown arch $ARCH"; return 1;;
|
||||
esac
|
||||
|
||||
if [ "$OUT_ROOT" -a "$PREBUILTS" ]; then
|
||||
local EXE="$1"
|
||||
if [ "$EXE" ] ; then
|
||||
EXE=$1
|
||||
if [[ $EXE =~ ^[^/].* ]] ; then
|
||||
EXE="system/bin/"$EXE
|
||||
fi
|
||||
else
|
||||
EXE="app_process"
|
||||
fi
|
||||
|
||||
local PORT="$2"
|
||||
if [ "$PORT" ] ; then
|
||||
PORT=$2
|
||||
else
|
||||
PORT=":5039"
|
||||
fi
|
||||
|
||||
local PID="$3"
|
||||
if [ "$PID" ] ; then
|
||||
if [[ ! "$PID" =~ ^[0-9]+$ ]] ; then
|
||||
PID=`pid $3`
|
||||
if [[ ! "$PID" =~ ^[0-9]+$ ]] ; then
|
||||
# that likely didn't work because of returning multiple processes
|
||||
# try again, filtering by root processes (don't contain colon)
|
||||
PID=`adb shell ps | \grep $3 | \grep -v ":" | awk '{print $2}'`
|
||||
if [[ ! "$PID" =~ ^[0-9]+$ ]]
|
||||
then
|
||||
echo "Couldn't resolve '$3' to single PID"
|
||||
return 1
|
||||
else
|
||||
echo ""
|
||||
echo "WARNING: multiple processes matching '$3' observed, using root process"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
adb forward "tcp$PORT" "tcp$PORT"
|
||||
local USE64BIT="$(is64bit $PID)"
|
||||
adb shell gdbserver$USE64BIT $PORT --attach $PID &
|
||||
sleep 2
|
||||
else
|
||||
echo ""
|
||||
echo "If you haven't done so already, do this first on the device:"
|
||||
echo " gdbserver $PORT /system/bin/$EXE"
|
||||
echo " or"
|
||||
echo " gdbserver $PORT --attach <PID>"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
OUT_SO_SYMBOLS=$OUT_SO_SYMBOLS$USE64BIT
|
||||
OUT_VENDOR_SO_SYMBOLS=$OUT_VENDOR_SO_SYMBOLS$USE64BIT
|
||||
|
||||
echo >|"$OUT_ROOT/gdbclient.cmds" "set solib-absolute-prefix $OUT_SYMBOLS"
|
||||
echo >>"$OUT_ROOT/gdbclient.cmds" "set solib-search-path $OUT_SO_SYMBOLS:$OUT_SO_SYMBOLS/hw:$OUT_SO_SYMBOLS/ssl/engines:$OUT_SO_SYMBOLS/drm:$OUT_SO_SYMBOLS/egl:$OUT_SO_SYMBOLS/soundfx:$OUT_VENDOR_SO_SYMBOLS:$OUT_VENDOR_SO_SYMBOLS/hw:$OUT_VENDOR_SO_SYMBOLS/egl"
|
||||
echo >>"$OUT_ROOT/gdbclient.cmds" "source $ANDROID_BUILD_TOP/development/scripts/gdb/dalvik.gdb"
|
||||
echo >>"$OUT_ROOT/gdbclient.cmds" "target remote $PORT"
|
||||
# Enable special debugging for ART processes.
|
||||
if [[ $EXE =~ (^|/)(app_process|dalvikvm)(|32|64)$ ]]; then
|
||||
echo >> "$OUT_ROOT/gdbclient.cmds" "art-on"
|
||||
fi
|
||||
echo >>"$OUT_ROOT/gdbclient.cmds" ""
|
||||
|
||||
local WHICH_GDB=
|
||||
# 64-bit exe found
|
||||
if [ "$USE64BIT" != "" ] ; then
|
||||
WHICH_GDB=$ANDROID_TOOLCHAIN/$GDB64
|
||||
# 32-bit exe / 32-bit platform
|
||||
elif [ "$(get_build_var TARGET_2ND_ARCH)" = "" ]; then
|
||||
WHICH_GDB=$ANDROID_TOOLCHAIN/$GDB
|
||||
# 32-bit exe / 64-bit platform
|
||||
else
|
||||
WHICH_GDB=$ANDROID_TOOLCHAIN_2ND_ARCH/$GDB
|
||||
fi
|
||||
|
||||
ddd --debugger $WHICH_GDB -x "$OUT_ROOT/gdbclient.cmds" "$OUT_EXE_SYMBOLS/$EXE"
|
||||
else
|
||||
echo "Unable to determine build system output dir."
|
||||
fi
|
||||
}
|
||||
|
||||
function cmremote()
|
||||
{
|
||||
if ! git rev-parse --git-dir &> /dev/null
|
||||
then
|
||||
echo ".git directory not found. Please run this from the root directory of the Android repository you wish to set up."
|
||||
return 1
|
||||
fi
|
||||
git remote rm cmremote 2> /dev/null
|
||||
GERRIT_REMOTE=$(git config --get remote.github.projectname)
|
||||
CMUSER=$(git config --get review.review.cyanogenmod.org.username)
|
||||
if [ -z "$CMUSER" ]
|
||||
then
|
||||
git remote add cmremote ssh://review.cyanogenmod.org:29418/$GERRIT_REMOTE
|
||||
else
|
||||
git remote add cmremote ssh://$CMUSER@review.cyanogenmod.org:29418/$GERRIT_REMOTE
|
||||
fi
|
||||
echo "Remote 'cmremote' created"
|
||||
}
|
||||
|
||||
function aospremote()
|
||||
{
|
||||
if ! git rev-parse --git-dir &> /dev/null
|
||||
then
|
||||
echo ".git directory not found. Please run this from the root directory of the Android repository you wish to set up."
|
||||
return 1
|
||||
fi
|
||||
git remote rm aosp 2> /dev/null
|
||||
PROJECT=$(pwd -P | sed "s#$ANDROID_BUILD_TOP\/##")
|
||||
if (echo $PROJECT | grep -qv "^device")
|
||||
then
|
||||
PFX="platform/"
|
||||
fi
|
||||
git remote add aosp https://android.googlesource.com/$PFX$PROJECT
|
||||
echo "Remote 'aosp' created"
|
||||
}
|
||||
|
||||
function cafremote()
|
||||
{
|
||||
if ! git rev-parse --git-dir &> /dev/null
|
||||
then
|
||||
echo ".git directory not found. Please run this from the root directory of the Android repository you wish to set up."
|
||||
return 1
|
||||
fi
|
||||
git remote rm caf 2> /dev/null
|
||||
PROJECT=$(pwd -P | sed "s#$ANDROID_BUILD_TOP\/##")
|
||||
if (echo $PROJECT | grep -qv "^device")
|
||||
then
|
||||
PFX="platform/"
|
||||
fi
|
||||
git remote add caf git://codeaurora.org/$PFX$PROJECT
|
||||
echo "Remote 'caf' created"
|
||||
}
|
||||
|
||||
function installboot()
|
||||
{
|
||||
if [ ! -e "$OUT/recovery/root/etc/recovery.fstab" ];
|
||||
then
|
||||
echo "No recovery.fstab found. Build recovery first."
|
||||
return 1
|
||||
fi
|
||||
if [ ! -e "$OUT/boot.img" ];
|
||||
then
|
||||
echo "No boot.img found. Run make bootimage first."
|
||||
return 1
|
||||
fi
|
||||
PARTITION=`grep "^\/boot" $OUT/recovery/root/etc/recovery.fstab | awk {'print $3'}`
|
||||
if [ -z "$PARTITION" ];
|
||||
then
|
||||
# Try for RECOVERY_FSTAB_VERSION = 2
|
||||
PARTITION=`grep "[[:space:]]\/boot[[:space:]]" $OUT/recovery/root/etc/recovery.fstab | awk {'print $1'}`
|
||||
PARTITION_TYPE=`grep "[[:space:]]\/boot[[:space:]]" $OUT/recovery/root/etc/recovery.fstab | awk {'print $3'}`
|
||||
if [ -z "$PARTITION" ];
|
||||
then
|
||||
echo "Unable to determine boot partition."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
adb start-server
|
||||
adb wait-for-online
|
||||
adb root
|
||||
sleep 1
|
||||
adb wait-for-online shell mount /system 2>&1 > /dev/null
|
||||
adb wait-for-online remount
|
||||
if (adb shell getprop ro.cm.device | grep -q "$CM_BUILD");
|
||||
then
|
||||
adb push $OUT/boot.img /cache/
|
||||
for i in $OUT/system/lib/modules/*;
|
||||
do
|
||||
adb push $i /system/lib/modules/
|
||||
done
|
||||
adb shell dd if=/cache/boot.img of=$PARTITION
|
||||
adb shell chmod 644 /system/lib/modules/*
|
||||
echo "Installation complete."
|
||||
else
|
||||
echo "The connected device does not appear to be $CM_BUILD, run away!"
|
||||
fi
|
||||
}
|
||||
|
||||
function installrecovery()
|
||||
{
|
||||
if [ ! -e "$OUT/recovery/root/etc/recovery.fstab" ];
|
||||
then
|
||||
echo "No recovery.fstab found. Build recovery first."
|
||||
return 1
|
||||
fi
|
||||
if [ ! -e "$OUT/recovery.img" ];
|
||||
then
|
||||
echo "No recovery.img found. Run make recoveryimage first."
|
||||
return 1
|
||||
fi
|
||||
PARTITION=`grep "^\/recovery" $OUT/recovery/root/etc/recovery.fstab | awk {'print $3'}`
|
||||
if [ -z "$PARTITION" ];
|
||||
then
|
||||
# Try for RECOVERY_FSTAB_VERSION = 2
|
||||
PARTITION=`grep "[[:space:]]\/recovery[[:space:]]" $OUT/recovery/root/etc/recovery.fstab | awk {'print $1'}`
|
||||
PARTITION_TYPE=`grep "[[:space:]]\/recovery[[:space:]]" $OUT/recovery/root/etc/recovery.fstab | awk {'print $3'}`
|
||||
if [ -z "$PARTITION" ];
|
||||
then
|
||||
echo "Unable to determine recovery partition."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
adb start-server
|
||||
adb wait-for-online
|
||||
adb root
|
||||
sleep 1
|
||||
adb wait-for-online shell mount /system 2>&1 >> /dev/null
|
||||
adb wait-for-online remount
|
||||
if (adb shell getprop ro.cm.device | grep -q "$CM_BUILD");
|
||||
then
|
||||
adb push $OUT/recovery.img /cache/
|
||||
adb shell dd if=/cache/recovery.img of=$PARTITION
|
||||
echo "Installation complete."
|
||||
else
|
||||
echo "The connected device does not appear to be $CM_BUILD, run away!"
|
||||
fi
|
||||
}
|
||||
|
||||
function makerecipe() {
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "No branch name provided."
|
||||
return 1
|
||||
fi
|
||||
cd android
|
||||
sed -i s/'default revision=.*'/'default revision="refs\/heads\/'$1'"'/ default.xml
|
||||
git commit -a -m "$1"
|
||||
cd ..
|
||||
|
||||
repo forall -c '
|
||||
|
||||
if [ "$REPO_REMOTE" = "github" ]
|
||||
then
|
||||
pwd
|
||||
cmremote
|
||||
git push cmremote HEAD:refs/heads/'$1'
|
||||
fi
|
||||
'
|
||||
}
|
||||
|
||||
function cmgerrit() {
|
||||
if [ "$(__detect_shell)" = "zsh" ]; then
|
||||
# zsh does not define FUNCNAME, derive from funcstack
|
||||
local FUNCNAME=$funcstack[1]
|
||||
fi
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
$FUNCNAME help
|
||||
return 1
|
||||
fi
|
||||
local user=`git config --get review.review.cyanogenmod.org.username`
|
||||
local review=`git config --get remote.github.review`
|
||||
local project=`git config --get remote.github.projectname`
|
||||
local command=$1
|
||||
shift
|
||||
case $command in
|
||||
help)
|
||||
if [ $# -eq 0 ]; then
|
||||
cat <<EOF
|
||||
Usage:
|
||||
$FUNCNAME COMMAND [OPTIONS] [CHANGE-ID[/PATCH-SET]][{@|^|~|:}ARG] [-- ARGS]
|
||||
|
||||
Commands:
|
||||
fetch Just fetch the change as FETCH_HEAD
|
||||
help Show this help, or for a specific command
|
||||
pull Pull a change into current branch
|
||||
push Push HEAD or a local branch to Gerrit for a specific branch
|
||||
|
||||
Any other Git commands that support refname would work as:
|
||||
git fetch URL CHANGE && git COMMAND OPTIONS FETCH_HEAD{@|^|~|:}ARG -- ARGS
|
||||
|
||||
See '$FUNCNAME help COMMAND' for more information on a specific command.
|
||||
|
||||
Example:
|
||||
$FUNCNAME checkout -b topic 1234/5
|
||||
works as:
|
||||
git fetch http://DOMAIN/p/PROJECT refs/changes/34/1234/5 \\
|
||||
&& git checkout -b topic FETCH_HEAD
|
||||
will checkout a new branch 'topic' base on patch-set 5 of change 1234.
|
||||
Patch-set 1 will be fetched if omitted.
|
||||
EOF
|
||||
return
|
||||
fi
|
||||
case $1 in
|
||||
__cmg_*) echo "For internal use only." ;;
|
||||
changes|for)
|
||||
if [ "$FUNCNAME" = "cmgerrit" ]; then
|
||||
echo "'$FUNCNAME $1' is deprecated."
|
||||
fi
|
||||
;;
|
||||
help) $FUNCNAME help ;;
|
||||
fetch|pull) cat <<EOF
|
||||
usage: $FUNCNAME $1 [OPTIONS] CHANGE-ID[/PATCH-SET]
|
||||
|
||||
works as:
|
||||
git $1 OPTIONS http://DOMAIN/p/PROJECT \\
|
||||
refs/changes/HASH/CHANGE-ID/{PATCH-SET|1}
|
||||
|
||||
Example:
|
||||
$FUNCNAME $1 1234
|
||||
will $1 patch-set 1 of change 1234
|
||||
EOF
|
||||
;;
|
||||
push) cat <<EOF
|
||||
usage: $FUNCNAME push [OPTIONS] [LOCAL_BRANCH:]REMOTE_BRANCH
|
||||
|
||||
works as:
|
||||
git push OPTIONS ssh://USER@DOMAIN:29418/PROJECT \\
|
||||
{LOCAL_BRANCH|HEAD}:refs/for/REMOTE_BRANCH
|
||||
|
||||
Example:
|
||||
$FUNCNAME push fix6789:gingerbread
|
||||
will push local branch 'fix6789' to Gerrit for branch 'gingerbread'.
|
||||
HEAD will be pushed from local if omitted.
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
$FUNCNAME __cmg_err_not_supported $1 && return
|
||||
cat <<EOF
|
||||
usage: $FUNCNAME $1 [OPTIONS] CHANGE-ID[/PATCH-SET][{@|^|~|:}ARG] [-- ARGS]
|
||||
|
||||
works as:
|
||||
git fetch http://DOMAIN/p/PROJECT \\
|
||||
refs/changes/HASH/CHANGE-ID/{PATCH-SET|1} \\
|
||||
&& git $1 OPTIONS FETCH_HEAD{@|^|~|:}ARG -- ARGS
|
||||
EOF
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
__cmg_get_ref)
|
||||
$FUNCNAME __cmg_err_no_arg $command $# && return 1
|
||||
local change_id patchset_id hash
|
||||
case $1 in
|
||||
*/*)
|
||||
change_id=${1%%/*}
|
||||
patchset_id=${1#*/}
|
||||
;;
|
||||
*)
|
||||
change_id=$1
|
||||
patchset_id=1
|
||||
;;
|
||||
esac
|
||||
hash=$(($change_id % 100))
|
||||
case $hash in
|
||||
[0-9]) hash="0$hash" ;;
|
||||
esac
|
||||
echo "refs/changes/$hash/$change_id/$patchset_id"
|
||||
;;
|
||||
fetch|pull)
|
||||
$FUNCNAME __cmg_err_no_arg $command $# help && return 1
|
||||
$FUNCNAME __cmg_err_not_repo && return 1
|
||||
local change=$1
|
||||
shift
|
||||
git $command $@ http://$review/p/$project \
|
||||
$($FUNCNAME __cmg_get_ref $change) || return 1
|
||||
;;
|
||||
push)
|
||||
$FUNCNAME __cmg_err_no_arg $command $# help && return 1
|
||||
$FUNCNAME __cmg_err_not_repo && return 1
|
||||
if [ -z "$user" ]; then
|
||||
echo >&2 "Gerrit username not found."
|
||||
return 1
|
||||
fi
|
||||
local local_branch remote_branch
|
||||
case $1 in
|
||||
*:*)
|
||||
local_branch=${1%:*}
|
||||
remote_branch=${1##*:}
|
||||
;;
|
||||
*)
|
||||
local_branch=HEAD
|
||||
remote_branch=$1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
git push $@ ssh://$user@$review:29418/$project \
|
||||
$local_branch:refs/for/$remote_branch || return 1
|
||||
;;
|
||||
changes|for)
|
||||
if [ "$FUNCNAME" = "cmgerrit" ]; then
|
||||
echo >&2 "'$FUNCNAME $command' is deprecated."
|
||||
fi
|
||||
;;
|
||||
__cmg_err_no_arg)
|
||||
if [ $# -lt 2 ]; then
|
||||
echo >&2 "'$FUNCNAME $command' missing argument."
|
||||
elif [ $2 -eq 0 ]; then
|
||||
if [ -n "$3" ]; then
|
||||
$FUNCNAME help $1
|
||||
else
|
||||
echo >&2 "'$FUNCNAME $1' missing argument."
|
||||
fi
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
__cmg_err_not_repo)
|
||||
if [ -z "$review" -o -z "$project" ]; then
|
||||
echo >&2 "Not currently in any reviewable repository."
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
__cmg_err_not_supported)
|
||||
$FUNCNAME __cmg_err_no_arg $command $# && return
|
||||
case $1 in
|
||||
#TODO: filter more git commands that don't use refname
|
||||
init|add|rm|mv|status|clone|remote|bisect|config|stash)
|
||||
echo >&2 "'$FUNCNAME $1' is not supported."
|
||||
;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
;;
|
||||
#TODO: other special cases?
|
||||
*)
|
||||
$FUNCNAME __cmg_err_not_supported $command && return 1
|
||||
$FUNCNAME __cmg_err_no_arg $command $# help && return 1
|
||||
$FUNCNAME __cmg_err_not_repo && return 1
|
||||
local args="$@"
|
||||
local change pre_args refs_arg post_args
|
||||
case "$args" in
|
||||
*--\ *)
|
||||
pre_args=${args%%-- *}
|
||||
post_args="-- ${args#*-- }"
|
||||
;;
|
||||
*) pre_args="$args" ;;
|
||||
esac
|
||||
args=($pre_args)
|
||||
pre_args=
|
||||
if [ ${#args[@]} -gt 0 ]; then
|
||||
change=${args[${#args[@]}-1]}
|
||||
fi
|
||||
if [ ${#args[@]} -gt 1 ]; then
|
||||
pre_args=${args[0]}
|
||||
for ((i=1; i<${#args[@]}-1; i++)); do
|
||||
pre_args="$pre_args ${args[$i]}"
|
||||
done
|
||||
fi
|
||||
while ((1)); do
|
||||
case $change in
|
||||
""|--)
|
||||
$FUNCNAME help $command
|
||||
return 1
|
||||
;;
|
||||
*@*)
|
||||
if [ -z "$refs_arg" ]; then
|
||||
refs_arg="@${change#*@}"
|
||||
change=${change%%@*}
|
||||
fi
|
||||
;;
|
||||
*~*)
|
||||
if [ -z "$refs_arg" ]; then
|
||||
refs_arg="~${change#*~}"
|
||||
change=${change%%~*}
|
||||
fi
|
||||
;;
|
||||
*^*)
|
||||
if [ -z "$refs_arg" ]; then
|
||||
refs_arg="^${change#*^}"
|
||||
change=${change%%^*}
|
||||
fi
|
||||
;;
|
||||
*:*)
|
||||
if [ -z "$refs_arg" ]; then
|
||||
refs_arg=":${change#*:}"
|
||||
change=${change%%:*}
|
||||
fi
|
||||
;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
$FUNCNAME fetch $change \
|
||||
&& git $command $pre_args FETCH_HEAD$refs_arg $post_args \
|
||||
|| return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
function cmrebase() {
|
||||
local repo=$1
|
||||
local refs=$2
|
||||
local pwd="$(pwd)"
|
||||
local dir="$(gettop)/$repo"
|
||||
|
||||
if [ -z $repo ] || [ -z $refs ]; then
|
||||
echo "CyanogenMod Gerrit Rebase Usage: "
|
||||
echo " cmrebase <path to project> <patch IDs on Gerrit>"
|
||||
echo " The patch IDs appear on the Gerrit commands that are offered."
|
||||
echo " They consist on a series of numbers and slashes, after the text"
|
||||
echo " refs/changes. For example, the ID in the following command is 26/8126/2"
|
||||
echo ""
|
||||
echo " git[...]ges_apps_Camera refs/changes/26/8126/2 && git cherry-pick FETCH_HEAD"
|
||||
echo ""
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -d $dir ]; then
|
||||
echo "Directory $dir doesn't exist in tree."
|
||||
return
|
||||
fi
|
||||
cd $dir
|
||||
repo=$(cat .git/config | grep git://github.com | awk '{ print $NF }' | sed s#git://github.com/##g)
|
||||
echo "Starting branch..."
|
||||
repo start tmprebase .
|
||||
echo "Bringing it up to date..."
|
||||
repo sync .
|
||||
echo "Fetching change..."
|
||||
git fetch "http://review.cyanogenmod.org/p/$repo" "refs/changes/$refs" && git cherry-pick FETCH_HEAD
|
||||
if [ "$?" != "0" ]; then
|
||||
echo "Error cherry-picking. Not uploading!"
|
||||
return
|
||||
fi
|
||||
echo "Uploading..."
|
||||
repo upload .
|
||||
echo "Cleaning up..."
|
||||
repo abandon tmprebase .
|
||||
cd $pwd
|
||||
}
|
||||
|
||||
function mka() {
|
||||
local T=$(gettop)
|
||||
if [ "$T" ]; then
|
||||
case `uname -s` in
|
||||
Darwin)
|
||||
make -C $T -j `sysctl hw.ncpu|cut -d" " -f2` "$@"
|
||||
;;
|
||||
*)
|
||||
mk_timer schedtool -B -n 1 -e ionice -n 1 make -C $T -j$(cat /proc/cpuinfo | grep "^processor" | wc -l) "$@"
|
||||
;;
|
||||
esac
|
||||
|
||||
else
|
||||
echo "Couldn't locate the top of the tree. Try setting TOP."
|
||||
fi
|
||||
}
|
||||
|
||||
function cmka() {
|
||||
if [ ! -z "$1" ]; then
|
||||
for i in "$@"; do
|
||||
case $i in
|
||||
bacon|otapackage|systemimage)
|
||||
mka installclean
|
||||
mka $i
|
||||
;;
|
||||
*)
|
||||
mka clean-$i
|
||||
mka $i
|
||||
;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
mka clean
|
||||
mka
|
||||
fi
|
||||
}
|
||||
|
||||
function mms() {
|
||||
local T=$(gettop)
|
||||
if [ -z "$T" ]
|
||||
then
|
||||
echo "Couldn't locate the top of the tree. Try setting TOP."
|
||||
return 1
|
||||
fi
|
||||
|
||||
case `uname -s` in
|
||||
Darwin)
|
||||
local NUM_CPUS=$(sysctl hw.ncpu|cut -d" " -f2)
|
||||
ONE_SHOT_MAKEFILE="__none__" \
|
||||
make -C $T -j $NUM_CPUS "$@"
|
||||
;;
|
||||
*)
|
||||
local NUM_CPUS=$(cat /proc/cpuinfo | grep "^processor" | wc -l)
|
||||
ONE_SHOT_MAKEFILE="__none__" \
|
||||
mk_timer schedtool -B -n 1 -e ionice -n 1 \
|
||||
make -C $T -j $NUM_CPUS "$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
function repolastsync() {
|
||||
RLSPATH="$ANDROID_BUILD_TOP/.repo/.repo_fetchtimes.json"
|
||||
RLSLOCAL=$(date -d "$(stat -c %z $RLSPATH)" +"%e %b %Y, %T %Z")
|
||||
RLSUTC=$(date -d "$(stat -c %z $RLSPATH)" -u +"%e %b %Y, %T %Z")
|
||||
echo "Last repo sync: $RLSLOCAL / $RLSUTC"
|
||||
}
|
||||
|
||||
function reposync() {
|
||||
case `uname -s` in
|
||||
Darwin)
|
||||
repo sync -j 4 "$@"
|
||||
;;
|
||||
*)
|
||||
schedtool -B -n 1 -e ionice -n 1 `which repo` sync -j 4 "$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
function repodiff() {
|
||||
if [ -z "$*" ]; then
|
||||
echo "Usage: repodiff <ref-from> [[ref-to] [--numstat]]"
|
||||
return
|
||||
fi
|
||||
diffopts=$* repo forall -c \
|
||||
'echo "$REPO_PATH ($REPO_REMOTE)"; git diff ${diffopts} 2>/dev/null ;'
|
||||
}
|
||||
|
||||
# Return success if adb is up and not in recovery
|
||||
function _adb_connected {
|
||||
{
|
||||
if [[ "$(adb get-state)" == device &&
|
||||
"$(adb shell test -e /sbin/recovery; echo $?)" == 0 ]]
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
} 2>/dev/null
|
||||
|
||||
return 1
|
||||
};
|
||||
|
||||
# Credit for color strip sed: http://goo.gl/BoIcm
|
||||
function dopush()
|
||||
{
|
||||
local func=$1
|
||||
shift
|
||||
|
||||
adb start-server # Prevent unexpected starting server message from adb get-state in the next line
|
||||
if ! _adb_connected; then
|
||||
echo "No device is online. Waiting for one..."
|
||||
echo "Please connect USB and/or enable USB debugging"
|
||||
until _adb_connected; do
|
||||
sleep 1
|
||||
done
|
||||
echo "Device Found."
|
||||
fi
|
||||
|
||||
if (adb shell getprop ro.cm.device | grep -q "$CM_BUILD") || [ "$FORCE_PUSH" = "true" ];
|
||||
then
|
||||
# retrieve IP and PORT info if we're using a TCP connection
|
||||
TCPIPPORT=$(adb devices | egrep '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+[^0-9]+' \
|
||||
| head -1 | awk '{print $1}')
|
||||
adb root &> /dev/null
|
||||
sleep 0.3
|
||||
if [ -n "$TCPIPPORT" ]
|
||||
then
|
||||
# adb root just killed our connection
|
||||
# so reconnect...
|
||||
adb connect "$TCPIPPORT"
|
||||
fi
|
||||
adb wait-for-device &> /dev/null
|
||||
sleep 0.3
|
||||
adb remount &> /dev/null
|
||||
|
||||
mkdir -p $OUT
|
||||
($func $*|tee $OUT/.log;return ${PIPESTATUS[0]})
|
||||
ret=$?;
|
||||
if [ $ret -ne 0 ]; then
|
||||
rm -f $OUT/.log;return $ret
|
||||
fi
|
||||
|
||||
# Install: <file>
|
||||
if [ `uname` = "Linux" ]; then
|
||||
LOC="$(cat $OUT/.log | sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' | grep '^Install: ' | cut -d ':' -f 2)"
|
||||
else
|
||||
LOC="$(cat $OUT/.log | sed -E "s/"$'\E'"\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]//g" | grep '^Install: ' | cut -d ':' -f 2)"
|
||||
fi
|
||||
|
||||
# Copy: <file>
|
||||
if [ `uname` = "Linux" ]; then
|
||||
LOC="$LOC $(cat $OUT/.log | sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' | grep '^Copy: ' | cut -d ':' -f 2)"
|
||||
else
|
||||
LOC="$LOC $(cat $OUT/.log | sed -E "s/"$'\E'"\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]//g" | grep '^Copy: ' | cut -d ':' -f 2)"
|
||||
fi
|
||||
|
||||
# If any files are going to /data, push an octal file permissions reader to device
|
||||
if [ -n "$(echo $LOC | egrep '(^|\s)/data')" ]; then
|
||||
CHKPERM="/data/local/tmp/chkfileperm.sh"
|
||||
(
|
||||
cat <<'EOF'
|
||||
#!/system/xbin/sh
|
||||
FILE=$@
|
||||
if [ -e $FILE ]; then
|
||||
ls -l $FILE | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf("%0o ",k);print}' | cut -d ' ' -f1
|
||||
fi
|
||||
EOF
|
||||
) > $OUT/.chkfileperm.sh
|
||||
echo "Pushing file permissions checker to device"
|
||||
adb push $OUT/.chkfileperm.sh $CHKPERM
|
||||
adb shell chmod 755 $CHKPERM
|
||||
rm -f $OUT/.chkfileperm.sh
|
||||
fi
|
||||
|
||||
stop_n_start=false
|
||||
for FILE in $(echo $LOC | tr " " "\n"); do
|
||||
# Make sure file is in $OUT/system or $OUT/data
|
||||
case $FILE in
|
||||
$OUT/system/*|$OUT/data/*)
|
||||
# Get target file name (i.e. /system/bin/adb)
|
||||
TARGET=$(echo $FILE | sed "s#$OUT##")
|
||||
;;
|
||||
*) continue ;;
|
||||
esac
|
||||
|
||||
case $TARGET in
|
||||
/data/*)
|
||||
# fs_config only sets permissions and se labels for files pushed to /system
|
||||
if [ -n "$CHKPERM" ]; then
|
||||
OLDPERM=$(adb shell $CHKPERM $TARGET)
|
||||
OLDPERM=$(echo $OLDPERM | tr -d '\r' | tr -d '\n')
|
||||
OLDOWN=$(adb shell ls -al $TARGET | awk '{print $2}')
|
||||
OLDGRP=$(adb shell ls -al $TARGET | awk '{print $3}')
|
||||
fi
|
||||
echo "Pushing: $TARGET"
|
||||
adb push $FILE $TARGET
|
||||
if [ -n "$OLDPERM" ]; then
|
||||
echo "Setting file permissions: $OLDPERM, $OLDOWN":"$OLDGRP"
|
||||
adb shell chown "$OLDOWN":"$OLDGRP" $TARGET
|
||||
adb shell chmod "$OLDPERM" $TARGET
|
||||
else
|
||||
echo "$TARGET did not exist previously, you should set file permissions manually"
|
||||
fi
|
||||
adb shell restorecon "$TARGET"
|
||||
;;
|
||||
/system/priv-app/SystemUI/SystemUI.apk|/system/framework/*)
|
||||
# Only need to stop services once
|
||||
if ! $stop_n_start; then
|
||||
adb shell stop
|
||||
stop_n_start=true
|
||||
fi
|
||||
echo "Pushing: $TARGET"
|
||||
adb push $FILE $TARGET
|
||||
;;
|
||||
*)
|
||||
echo "Pushing: $TARGET"
|
||||
adb push $FILE $TARGET
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ -n "$CHKPERM" ]; then
|
||||
adb shell rm $CHKPERM
|
||||
fi
|
||||
if $stop_n_start; then
|
||||
adb shell start
|
||||
fi
|
||||
rm -f $OUT/.log
|
||||
return 0
|
||||
else
|
||||
echo "The connected device does not appear to be $CM_BUILD, run away!"
|
||||
fi
|
||||
}
|
||||
|
||||
alias mmp='dopush mm'
|
||||
alias mmmp='dopush mmm'
|
||||
alias mmap='dopush mma'
|
||||
alias mkap='dopush mka'
|
||||
alias cmkap='dopush cmka'
|
||||
|
||||
function repopick() {
|
||||
T=$(gettop)
|
||||
$T/vendor/cm/build/tools/repopick.py $@
|
||||
}
|
||||
|
||||
function fixup_common_out_dir() {
|
||||
common_out_dir=$(get_build_var OUT_DIR)/target/common
|
||||
target_device=$(get_build_var TARGET_DEVICE)
|
||||
if [ ! -z $CM_FIXUP_COMMON_OUT ]; then
|
||||
if [ -d ${common_out_dir} ] && [ ! -L ${common_out_dir} ]; then
|
||||
mv ${common_out_dir} ${common_out_dir}-${target_device}
|
||||
ln -s ${common_out_dir}-${target_device} ${common_out_dir}
|
||||
else
|
||||
[ -L ${common_out_dir} ] && rm ${common_out_dir}
|
||||
mkdir -p ${common_out_dir}-${target_device}
|
||||
ln -s ${common_out_dir}-${target_device} ${common_out_dir}
|
||||
fi
|
||||
else
|
||||
[ -L ${common_out_dir} ] && rm ${common_out_dir}
|
||||
mkdir -p ${common_out_dir}
|
||||
fi
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID1TCCAr2gAwIBAgIJANO67t8hIti6MA0GCSqGSIb3DQEBBQUAMIGAMQswCQYD
|
||||
VQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEX
|
||||
MBUGA1UECgwOQ3lhbm9nZW4sIEluYy4xGzAZBgNVBAsMElJlbGVhc2UgTWFuYWdl
|
||||
bWVudDEUMBIGA1UEAwwLRGV2ZWxvcG1lbnQwHhcNMTQwNDI4MjAyODM3WhcNNDEw
|
||||
OTEzMjAyODM3WjCBgDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24x
|
||||
EDAOBgNVBAcMB1NlYXR0bGUxFzAVBgNVBAoMDkN5YW5vZ2VuLCBJbmMuMRswGQYD
|
||||
VQQLDBJSZWxlYXNlIE1hbmFnZW1lbnQxFDASBgNVBAMMC0RldmVsb3BtZW50MIIB
|
||||
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz/V9RvYnr18fraPWNeQEZNeg
|
||||
Kc0A3QskImQyGY22EGBZ63KUxa6zAfAug0OYSjofVJRaTtdvBXjO/C71XZRh4wun
|
||||
xhOUAJt8zIJ0lRx8GMC0GHzePEnEVvoiu3zSAPHCNf5lmdhyhccMOtC18J+evPf4
|
||||
EVBb3cis+F1m6ZoZKPgSFBR5A9CV5Tai8iiZluGGg15Wt12Rp2vmbmQxiOJZxBs4
|
||||
Ps40XR5gjO1q4R3HiGnFyql9qeecwaTUWXAd76lhNiLUr7K8IRs+96i+t5vSKajB
|
||||
M8O99BtYyBtf8ItMnHSZJxtsMw+TFXNLmMtaQarpsjp0LLGuHb/vsrjgBPvzsQID
|
||||
AQABo1AwTjAdBgNVHQ4EFgQUTpNgXBqV7j+33bi8B80YLQq6EL8wHwYDVR0jBBgw
|
||||
FoAUTpNgXBqV7j+33bi8B80YLQq6EL8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B
|
||||
AQUFAAOCAQEAVlVBNksK+1C3J8uQ9kVemYMozfbboV9c4PLbtVzNSO8vwZ3X5E4T
|
||||
2zfQPcFsfSMIa51a1tETBcDA6k+72xHZ+xEQJQNrX+o1F1RIIrXp0OKAz/k5cXyk
|
||||
OS0+nd0EXP/A1EW0m8N/X6E9wpRkIhfqtEsqeCf8GH7O9Ua2qHZ9zkTBpbAVH0oe
|
||||
ZWorHBdo3GdMJ5vcjFqnDdRs8F0BnZmjS+NrgXRLhLb6ZARS/bkUQyr5TX82dgG6
|
||||
vzvKsdKyX34gsKAsjxwLWo7XXgehFfjY+SGjjilJtardr+y/KlHNEw9s9aLe+Xny
|
||||
Qoa9j9Ut6/KwRaC6lSEQ7HZk6SdzFsdugA==
|
||||
-----END CERTIFICATE-----
|
@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDZDCCAkygAwIBAgIEUfbexjANBgkqhkiG9w0BAQUFADB0MQswCQYDVQQGEwJV
|
||||
UzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxFjAUBgNVBAoTDUN5YW5v
|
||||
Z2VuIEluYy4xFjAUBgNVBAsTDUN5YW5vZ2VuIEluYy4xFjAUBgNVBAMTDUN5YW5v
|
||||
Z2VuIEluYy4wHhcNMTMwNzI5MjEyOTQyWhcNNDAxMjE0MjEyOTQyWjB0MQswCQYD
|
||||
VQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxFjAUBgNVBAoT
|
||||
DUN5YW5vZ2VuIEluYy4xFjAUBgNVBAsTDUN5YW5vZ2VuIEluYy4xFjAUBgNVBAMT
|
||||
DUN5YW5vZ2VuIEluYy4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCP
|
||||
+K2NPqdZ6UmexXQ8tsc2TkLXYhiuEsifO66qlpwsTTw1522HcbKPVoPRr/JBXqOv
|
||||
E3K0HuZ/IsYYGsP/wJWWvpaWs+5xC+YkLkittK2uUzTqndpLFiDRAeICKpvDJI57
|
||||
Z0DkzVYXBPn+yw+x8ttjT/vWcJ3PEVYuew8MYPUOgKpdZlQtUBeoEBDSL8JPGViq
|
||||
e6jWOlSAWekhlgb+wb9RoXhu/v2HYzp89GG0sIrAgj7vZCior5XuFmm8eWhqUhTp
|
||||
TUBv/nNI/ORYt3G8IQyI2pJN1GNPAAv1uA5i4y/deX1x4GCWyN9feiD9fOj2oc3z
|
||||
Hwf5Frs9BjOb9XMXecbNAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAGudhFe9VnES
|
||||
fWynTYO4kWNlMC++yB6qD3pHW6HtBiaANj9wxrLCTFzf+boHNPeZ8HDkW01zAaQK
|
||||
fd9/fnGmHf4q/QvxrvGbnb3Fqhw+2hknbbMUoAa+Qp+2ouf9oJaNRquZ+rHEHX8g
|
||||
Rx8wGyvjaWYfQrwyZRgXj/Jrc/NXxQCmSJeexHVNXgQD6aOLHJYrJ+s+U/hwVNiM
|
||||
5L+psOh89itwt8DGGSLW16HjQKmPPbWbqxgnfRbOlxWrLDq3agcrskYpDP2aGGBA
|
||||
5STq/bvh9yZkrNYvMGzrXDhcJ44QRS8e1Jw/ZtfFvJD192e7KKVdy7CJWmOckCNK
|
||||
gl0KCQ3MBx4=
|
||||
-----END CERTIFICATE-----
|
@ -0,0 +1,53 @@
|
||||
#----------------------------------------------------------------------
|
||||
# Generate device tree image (dt.img)
|
||||
#----------------------------------------------------------------------
|
||||
ifeq ($(strip $(BOARD_CUSTOM_BOOTIMG_MK)),)
|
||||
ifeq ($(strip $(BOARD_KERNEL_SEPARATED_DT)),true)
|
||||
ifneq ($(strip $(BOARD_KERNEL_PREBUILT_DT)),true)
|
||||
ifeq ($(strip $(BUILD_TINY_ANDROID)),true)
|
||||
include device/qcom/common/dtbtool/Android.mk
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(TARGET_CUSTOM_DTBTOOL)),)
|
||||
DTBTOOL_NAME := dtbToolCM
|
||||
else
|
||||
DTBTOOL_NAME := $(TARGET_CUSTOM_DTBTOOL)
|
||||
endif
|
||||
|
||||
DTBTOOL := $(HOST_OUT_EXECUTABLES)/$(DTBTOOL_NAME)$(HOST_EXECUTABLE_SUFFIX)
|
||||
|
||||
INSTALLED_DTIMAGE_TARGET := $(PRODUCT_OUT)/dt.img
|
||||
|
||||
ifeq ($(strip $(TARGET_CUSTOM_DTBTOOL)),)
|
||||
# dtbToolCM will search subdirectories
|
||||
possible_dtb_dirs = $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/
|
||||
else
|
||||
# Most specific paths must come first in possible_dtb_dirs
|
||||
possible_dtb_dirs = $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/dts/ $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/
|
||||
endif
|
||||
|
||||
define build-dtimage-target
|
||||
$(call pretty,"Target dt image: $@")
|
||||
$(hide) for dir in $(possible_dtb_dirs); do \
|
||||
if [ -d "$$dir" ]; then \
|
||||
dtb_dir="$$dir"; \
|
||||
break; \
|
||||
fi; \
|
||||
done; \
|
||||
$(DTBTOOL) $(BOARD_DTBTOOL_ARGS) -o $@ -s $(BOARD_KERNEL_PAGESIZE) -p $(KERNEL_OUT)/scripts/dtc/ "$$dtb_dir";
|
||||
$(hide) chmod a+r $@
|
||||
endef
|
||||
|
||||
$(INSTALLED_DTIMAGE_TARGET): $(DTBTOOL) $(INSTALLED_KERNEL_TARGET)
|
||||
$(build-dtimage-target)
|
||||
@echo "Made DT image: $@"
|
||||
|
||||
ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_DTIMAGE_TARGET)
|
||||
ALL_MODULES.$(LOCAL_MODULE).INSTALLED += $(INSTALLED_DTIMAGE_TARGET)
|
||||
|
||||
.PHONY: dtimage
|
||||
dtimage: $(INSTALLED_DTIMAGE_TARGET)
|
||||
|
||||
endif
|
||||
endif
|
||||
endif
|
@ -0,0 +1,373 @@
|
||||
# Copyright (C) 2012 The CyanogenMod Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
# Android makefile to build kernel as a part of Android Build
|
||||
#
|
||||
# Configuration
|
||||
# =============
|
||||
#
|
||||
# These config vars are usually set in BoardConfig.mk:
|
||||
#
|
||||
# TARGET_KERNEL_SOURCE = Kernel source dir, optional, defaults
|
||||
# to kernel/$(TARGET_DEVICE_DIR)
|
||||
# TARGET_KERNEL_CONFIG = Kernel defconfig
|
||||
# TARGET_KERNEL_VARIANT_CONFIG = Variant defconfig, optional
|
||||
# TARGET_KERNEL_SELINUX_CONFIG = SELinux defconfig, optional
|
||||
# TARGET_KERNEL_ADDITIONAL_CONFIG = Additional defconfig, optional
|
||||
# TARGET_KERNEL_ARCH = Kernel Arch
|
||||
# TARGET_KERNEL_HEADER_ARCH = Optional Arch for kernel headers if
|
||||
# different from TARGET_KERNEL_ARCH
|
||||
# TARGET_USES_UNCOMPRESSED_KERNEL = 'true' if Kernel is uncompressed,
|
||||
# optional, defaults to false
|
||||
# TARGET_KERNEL_CROSS_COMPILE_PREFIX = Compiler prefix (e.g. arm-eabi-)
|
||||
# defaults to arm-linux-androideabi- for arm
|
||||
# aarch64-linux-android- for arm64
|
||||
# x86_64-linux-android- for x86
|
||||
#
|
||||
# BOARD_KERNEL_IMAGE_NAME = Built image name, optional,
|
||||
# defaults to Image.gz on arm64
|
||||
# defaults to Image if TARGET_USES_UNCOMPRESSED_KERNEL
|
||||
# defaults to zImage otherwise
|
||||
#
|
||||
# KERNEL_TOOLCHAIN_PREFIX = Overrides TARGET_KERNEL_CROSS_COMPILE_PREFIX,
|
||||
# Set this var in shell to override
|
||||
# toolchain specified in BoardConfig.mk
|
||||
# KERNEL_TOOLCHAIN = Path to toolchain, if unset, assumes
|
||||
# TARGET_KERNEL_CROSS_COMPILE_PREFIX
|
||||
# is in PATH
|
||||
# USE_CCACHE = Enable ccache (global Android flag)
|
||||
#
|
||||
# NEED_KERNEL_MODULE_ROOT = Optional, if true, install kernel
|
||||
# modules in root instead of system
|
||||
|
||||
|
||||
TARGET_AUTO_KDIR := $(shell echo $(TARGET_DEVICE_DIR) | sed -e 's/^device/kernel/g')
|
||||
|
||||
## Externally influenced variables
|
||||
# kernel location - optional, defaults to kernel/<vendor>/<device>
|
||||
TARGET_KERNEL_SOURCE ?= $(TARGET_AUTO_KDIR)
|
||||
KERNEL_SRC := $(TARGET_KERNEL_SOURCE)
|
||||
# kernel configuration - mandatory
|
||||
KERNEL_DEFCONFIG := $(TARGET_KERNEL_CONFIG)
|
||||
VARIANT_DEFCONFIG := $(TARGET_KERNEL_VARIANT_CONFIG)
|
||||
SELINUX_DEFCONFIG := $(TARGET_KERNEL_SELINUX_CONFIG)
|
||||
|
||||
## Internal variables
|
||||
KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ
|
||||
KERNEL_CONFIG := $(KERNEL_OUT)/.config
|
||||
KERNEL_OUT_STAMP := $(KERNEL_OUT)/.mkdir_stamp
|
||||
|
||||
TARGET_KERNEL_ARCH := $(strip $(TARGET_KERNEL_ARCH))
|
||||
ifeq ($(TARGET_KERNEL_ARCH),)
|
||||
KERNEL_ARCH := $(TARGET_ARCH)
|
||||
else
|
||||
KERNEL_ARCH := $(TARGET_KERNEL_ARCH)
|
||||
endif
|
||||
|
||||
ifeq ($(KERNEL_ARCH),x86_64)
|
||||
KERNEL_DEFCONFIG_ARCH := x86
|
||||
else
|
||||
KERNEL_DEFCONFIG_ARCH := $(KERNEL_ARCH)
|
||||
endif
|
||||
KERNEL_DEFCONFIG_SRC := $(KERNEL_SRC)/arch/$(KERNEL_DEFCONFIG_ARCH)/configs/$(KERNEL_DEFCONFIG)
|
||||
|
||||
TARGET_KERNEL_HEADER_ARCH := $(strip $(TARGET_KERNEL_HEADER_ARCH))
|
||||
ifeq ($(TARGET_KERNEL_HEADER_ARCH),)
|
||||
KERNEL_HEADER_ARCH := $(KERNEL_ARCH)
|
||||
else
|
||||
KERNEL_HEADER_ARCH := $(TARGET_KERNEL_HEADER_ARCH)
|
||||
endif
|
||||
|
||||
KERNEL_HEADER_DEFCONFIG := $(strip $(KERNEL_HEADER_DEFCONFIG))
|
||||
ifeq ($(KERNEL_HEADER_DEFCONFIG),)
|
||||
KERNEL_HEADER_DEFCONFIG := $(KERNEL_DEFCONFIG)
|
||||
endif
|
||||
|
||||
|
||||
ifneq ($(BOARD_KERNEL_IMAGE_NAME),)
|
||||
TARGET_PREBUILT_INT_KERNEL_TYPE := $(BOARD_KERNEL_IMAGE_NAME)
|
||||
else
|
||||
ifeq ($(TARGET_USES_UNCOMPRESSED_KERNEL),true)
|
||||
TARGET_PREBUILT_INT_KERNEL_TYPE := Image
|
||||
else
|
||||
ifeq ($(KERNEL_ARCH),arm64)
|
||||
TARGET_PREBUILT_INT_KERNEL_TYPE := Image.gz
|
||||
else
|
||||
TARGET_PREBUILT_INT_KERNEL_TYPE := zImage
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/$(TARGET_PREBUILT_INT_KERNEL_TYPE)
|
||||
|
||||
# Clear this first to prevent accidental poisoning from env
|
||||
MAKE_FLAGS :=
|
||||
|
||||
ifeq ($(KERNEL_ARCH),arm64)
|
||||
# Avoid "unsupported RELA relocation: 311" errors (R_AARCH64_ADR_GOT_PAGE)
|
||||
MAKE_FLAGS += CFLAGS_MODULE="-fno-pic"
|
||||
ifeq ($(TARGET_ARCH),arm)
|
||||
KERNEL_CONFIG_OVERRIDE := CONFIG_ANDROID_BINDER_IPC_32BIT=y
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(TARGET_KERNEL_ADDITIONAL_CONFIG),)
|
||||
KERNEL_ADDITIONAL_CONFIG := $(TARGET_KERNEL_ADDITIONAL_CONFIG)
|
||||
KERNEL_ADDITIONAL_CONFIG_SRC := $(KERNEL_SRC)/arch/$(KERNEL_ARCH)/configs/$(KERNEL_ADDITIONAL_CONFIG)
|
||||
ifeq ("$(wildcard $(KERNEL_ADDITIONAL_CONFIG_SRC))","")
|
||||
$(warning TARGET_KERNEL_ADDITIONAL_CONFIG '$(TARGET_KERNEL_ADDITIONAL_CONFIG)' doesn't exist)
|
||||
KERNEL_ADDITIONAL_CONFIG_SRC := /dev/null
|
||||
endif
|
||||
else
|
||||
KERNEL_ADDITIONAL_CONFIG_SRC := /dev/null
|
||||
endif
|
||||
|
||||
## Do be discontinued in a future version. Notify builder about target
|
||||
## kernel format requirement
|
||||
ifeq ($(BOARD_KERNEL_IMAGE_NAME),)
|
||||
ifeq ($(BOARD_USES_UBOOT),true)
|
||||
$(error "Please set BOARD_KERNEL_IMAGE_NAME to uImage")
|
||||
else ifeq ($(BOARD_USES_UNCOMPRESSED_BOOT),true)
|
||||
$(error "Please set BOARD_KERNEL_IMAGE_NAME to Image")
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq "$(wildcard $(KERNEL_SRC) )" ""
|
||||
ifneq ($(TARGET_PREBUILT_KERNEL),)
|
||||
HAS_PREBUILT_KERNEL := true
|
||||
NEEDS_KERNEL_COPY := true
|
||||
else
|
||||
$(foreach cf,$(PRODUCT_COPY_FILES), \
|
||||
$(eval _src := $(call word-colon,1,$(cf))) \
|
||||
$(eval _dest := $(call word-colon,2,$(cf))) \
|
||||
$(ifeq kernel,$(_dest), \
|
||||
$(eval HAS_PREBUILT_KERNEL := true)))
|
||||
endif
|
||||
|
||||
ifneq ($(HAS_PREBUILT_KERNEL),)
|
||||
$(warning ***************************************************************)
|
||||
$(warning * Using prebuilt kernel binary instead of source *)
|
||||
$(warning * THIS IS DEPRECATED, AND WILL BE DISCONTINUED *)
|
||||
$(warning * Please configure your device to download the kernel *)
|
||||
$(warning * source repository to $(KERNEL_SRC))
|
||||
$(warning * See http://wiki.cyanogenmod.org/w/Doc:_integrated_kernel_building)
|
||||
$(warning * for more information *)
|
||||
$(warning ***************************************************************)
|
||||
FULL_KERNEL_BUILD := false
|
||||
KERNEL_BIN := $(TARGET_PREBUILT_KERNEL)
|
||||
else
|
||||
$(warning ***************************************************************)
|
||||
$(warning * *)
|
||||
$(warning * No kernel source found, and no fallback prebuilt defined. *)
|
||||
$(warning * Please make sure your device is properly configured to *)
|
||||
$(warning * download the kernel repository to $(KERNEL_SRC))
|
||||
$(warning * and add the TARGET_KERNEL_CONFIG variable to BoardConfig.mk *)
|
||||
$(warning * *)
|
||||
$(warning * As an alternative, define the TARGET_PREBUILT_KERNEL *)
|
||||
$(warning * variable with the path to the prebuilt binary kernel image *)
|
||||
$(warning * in your BoardConfig.mk file *)
|
||||
$(warning * *)
|
||||
$(warning ***************************************************************)
|
||||
$(error "NO KERNEL")
|
||||
endif
|
||||
else
|
||||
NEEDS_KERNEL_COPY := true
|
||||
ifeq ($(TARGET_KERNEL_CONFIG),)
|
||||
$(warning **********************************************************)
|
||||
$(warning * Kernel source found, but no configuration was defined *)
|
||||
$(warning * Please add the TARGET_KERNEL_CONFIG variable to your *)
|
||||
$(warning * BoardConfig.mk file *)
|
||||
$(warning **********************************************************)
|
||||
# $(error "NO KERNEL CONFIG")
|
||||
else
|
||||
#$(info Kernel source found, building it)
|
||||
FULL_KERNEL_BUILD := true
|
||||
KERNEL_BIN := $(TARGET_PREBUILT_INT_KERNEL)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(FULL_KERNEL_BUILD),true)
|
||||
|
||||
KERNEL_HEADERS_INSTALL := $(KERNEL_OUT)/usr
|
||||
KERNEL_HEADERS_INSTALL_STAMP := $(KERNEL_OUT)/.headers_install_stamp
|
||||
|
||||
ifeq ($(NEED_KERNEL_MODULE_ROOT),true)
|
||||
KERNEL_MODULES_INSTALL := root
|
||||
KERNEL_MODULES_OUT := $(TARGET_ROOT_OUT)/lib/modules
|
||||
else
|
||||
KERNEL_MODULES_INSTALL := system
|
||||
KERNEL_MODULES_OUT := $(TARGET_OUT)/lib/modules
|
||||
endif
|
||||
|
||||
TARGET_KERNEL_CROSS_COMPILE_PREFIX := $(strip $(TARGET_KERNEL_CROSS_COMPILE_PREFIX))
|
||||
ifneq ($(TARGET_KERNEL_CROSS_COMPILE_PREFIX),)
|
||||
KERNEL_TOOLCHAIN_PREFIX ?= $(TARGET_KERNEL_CROSS_COMPILE_PREFIX)
|
||||
else ifeq ($(TARGET_ARCH),arm64)
|
||||
KERNEL_TOOLCHAIN_PREFIX ?= aarch64-linux-android-
|
||||
else ifeq ($(TARGET_ARCH),arm)
|
||||
KERNEL_TOOLCHAIN_PREFIX ?= arm-linux-androideabi-
|
||||
else ifeq ($(TARGET_ARCH),x86)
|
||||
KERNEL_TOOLCHAIN_PREFIX ?= x86_64-linux-android-
|
||||
endif
|
||||
|
||||
ifeq ($(KERNEL_TOOLCHAIN),)
|
||||
KERNEL_TOOLCHAIN_PATH := $(KERNEL_TOOLCHAIN_PREFIX)
|
||||
else
|
||||
ifneq ($(KERNEL_TOOLCHAIN_PREFIX),)
|
||||
KERNEL_TOOLCHAIN_PATH := $(KERNEL_TOOLCHAIN)/$(KERNEL_TOOLCHAIN_PREFIX)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(USE_CCACHE),)
|
||||
ccache := $(ANDROID_BUILD_TOP)/prebuilts/misc/$(HOST_PREBUILT_TAG)/ccache/ccache
|
||||
# Check that the executable is here.
|
||||
ccache := $(strip $(wildcard $(ccache)))
|
||||
endif
|
||||
|
||||
KERNEL_CROSS_COMPILE := CROSS_COMPILE="$(ccache) $(KERNEL_TOOLCHAIN_PATH)"
|
||||
ccache =
|
||||
|
||||
define mv-modules
|
||||
mdpath=`find $(KERNEL_MODULES_OUT) -type f -name modules.order`;\
|
||||
if [ "$$mdpath" != "" ];then\
|
||||
mpath=`dirname $$mdpath`;\
|
||||
ko=`find $$mpath/kernel -type f -name *.ko`;\
|
||||
for i in $$ko; do $(KERNEL_TOOLCHAIN_PATH)strip --strip-unneeded $$i;\
|
||||
mv $$i $(KERNEL_MODULES_OUT)/; done;\
|
||||
fi
|
||||
endef
|
||||
|
||||
define clean-module-folder
|
||||
mdpath=`find $(KERNEL_MODULES_OUT) -type f -name modules.order`;\
|
||||
if [ "$$mdpath" != "" ];then\
|
||||
mpath=`dirname $$mdpath`; rm -rf $$mpath;\
|
||||
fi
|
||||
endef
|
||||
|
||||
ifeq ($(HOST_OS),darwin)
|
||||
MAKE_FLAGS += C_INCLUDE_PATH=$(ANDROID_BUILD_TOP)/external/elfutils/libelf/
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_KERNEL_MODULES),)
|
||||
TARGET_KERNEL_MODULES := no-external-modules
|
||||
endif
|
||||
|
||||
$(KERNEL_OUT_STAMP):
|
||||
$(hide) mkdir -p $(KERNEL_OUT)
|
||||
$(hide) rm -rf $(KERNEL_MODULES_OUT)
|
||||
$(hide) mkdir -p $(KERNEL_MODULES_OUT)
|
||||
$(hide) touch $@
|
||||
|
||||
KERNEL_ADDITIONAL_CONFIG_OUT := $(KERNEL_OUT)/.additional_config
|
||||
|
||||
.PHONY: force_additional_config
|
||||
$(KERNEL_ADDITIONAL_CONFIG_OUT): force_additional_config
|
||||
$(hide) cmp -s $(KERNEL_ADDITIONAL_CONFIG_SRC) $@ || cp $(KERNEL_ADDITIONAL_CONFIG_SRC) $@;
|
||||
|
||||
$(KERNEL_CONFIG): $(KERNEL_OUT_STAMP) $(KERNEL_DEFCONFIG_SRC) $(KERNEL_ADDITIONAL_CONFIG_OUT)
|
||||
@echo "Building Kernel Config"
|
||||
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) VARIANT_DEFCONFIG=$(VARIANT_DEFCONFIG) SELINUX_DEFCONFIG=$(SELINUX_DEFCONFIG) $(KERNEL_DEFCONFIG)
|
||||
$(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
|
||||
echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
|
||||
echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \
|
||||
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) oldconfig; fi
|
||||
$(hide) if [ ! -z "$(KERNEL_ADDITIONAL_CONFIG)" ]; then \
|
||||
echo "Using additional config '$(KERNEL_ADDITIONAL_CONFIG)'"; \
|
||||
$(KERNEL_SRC)/scripts/kconfig/merge_config.sh -m -O $(KERNEL_OUT) $(KERNEL_OUT)/.config $(KERNEL_SRC)/arch/$(KERNEL_ARCH)/configs/$(KERNEL_ADDITIONAL_CONFIG); \
|
||||
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) KCONFIG_ALLCONFIG=$(KERNEL_OUT)/.config alldefconfig; fi
|
||||
|
||||
TARGET_KERNEL_BINARIES: $(KERNEL_OUT_STAMP) $(KERNEL_CONFIG) $(KERNEL_HEADERS_INSTALL_STAMP)
|
||||
@echo "Building Kernel"
|
||||
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(TARGET_PREBUILT_INT_KERNEL_TYPE)
|
||||
$(hide) if grep -q 'CONFIG_OF=y' $(KERNEL_CONFIG) ; \
|
||||
then \
|
||||
echo "Building DTBs" ; \
|
||||
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) dtbs ; \
|
||||
else \
|
||||
echo "DTBs not enabled" ; \
|
||||
fi ;
|
||||
$(hide) if grep -q 'CONFIG_MODULES=y' $(KERNEL_CONFIG) ; \
|
||||
then \
|
||||
echo "Building Kernel Modules" ; \
|
||||
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) modules && \
|
||||
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) INSTALL_MOD_PATH=../../$(KERNEL_MODULES_INSTALL) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) modules_install && \
|
||||
$(mv-modules) && \
|
||||
$(clean-module-folder) ; \
|
||||
else \
|
||||
echo "Kernel Modules not enabled" ; \
|
||||
fi ;
|
||||
|
||||
|
||||
$(TARGET_KERNEL_MODULES): TARGET_KERNEL_BINARIES
|
||||
|
||||
$(TARGET_PREBUILT_INT_KERNEL): $(TARGET_KERNEL_MODULES)
|
||||
$(mv-modules)
|
||||
$(clean-module-folder)
|
||||
|
||||
$(KERNEL_HEADERS_INSTALL_STAMP): $(KERNEL_OUT_STAMP) $(KERNEL_CONFIG)
|
||||
@echo "Building Kernel Headers"
|
||||
$(hide) if [ ! -z "$(KERNEL_HEADER_DEFCONFIG)" ]; then \
|
||||
rm -f ../$(KERNEL_CONFIG); \
|
||||
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_HEADER_ARCH) $(KERNEL_CROSS_COMPILE) VARIANT_DEFCONFIG=$(VARIANT_DEFCONFIG) SELINUX_DEFCONFIG=$(SELINUX_DEFCONFIG) $(KERNEL_HEADER_DEFCONFIG); \
|
||||
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_HEADER_ARCH) $(KERNEL_CROSS_COMPILE) headers_install; fi
|
||||
$(hide) if [ "$(KERNEL_HEADER_DEFCONFIG)" != "$(KERNEL_DEFCONFIG)" ]; then \
|
||||
echo "Used a different defconfig for header generation"; \
|
||||
rm -f ../$(KERNEL_CONFIG); \
|
||||
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) VARIANT_DEFCONFIG=$(VARIANT_DEFCONFIG) SELINUX_DEFCONFIG=$(SELINUX_DEFCONFIG) $(KERNEL_DEFCONFIG); fi
|
||||
$(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
|
||||
echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
|
||||
echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \
|
||||
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) oldconfig; fi
|
||||
$(hide) if [ ! -z "$(KERNEL_ADDITIONAL_CONFIG)" ]; then \
|
||||
echo "Using additional config '$(KERNEL_ADDITIONAL_CONFIG)'"; \
|
||||
$(KERNEL_SRC)/scripts/kconfig/merge_config.sh -m -O $(KERNEL_OUT) $(KERNEL_OUT)/.config $(KERNEL_SRC)/arch/$(KERNEL_ARCH)/configs/$(KERNEL_ADDITIONAL_CONFIG); \
|
||||
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) KCONFIG_ALLCONFIG=$(KERNEL_OUT)/.config alldefconfig; fi
|
||||
$(hide) touch $@
|
||||
|
||||
# provide this rule because there are dependencies on this throughout the repo
|
||||
$(KERNEL_HEADERS_INSTALL): $(KERNEL_HEADERS_INSTALL_STAMP)
|
||||
|
||||
kerneltags: $(KERNEL_OUT_STAMP) $(KERNEL_CONFIG)
|
||||
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) tags
|
||||
|
||||
kernelconfig: KERNELCONFIG_MODE := menuconfig
|
||||
kernelxconfig: KERNELCONFIG_MODE := xconfig
|
||||
kernelxconfig kernelconfig: $(KERNEL_OUT_STAMP)
|
||||
$(MAKE) $(MAKE_FLAGS) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNEL_DEFCONFIG)
|
||||
env KCONFIG_NOTIMESTAMP=true \
|
||||
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) $(KERNELCONFIG_MODE)
|
||||
env KCONFIG_NOTIMESTAMP=true \
|
||||
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) savedefconfig
|
||||
cp $(KERNEL_OUT)/defconfig $(KERNEL_DEFCONFIG_SRC)
|
||||
|
||||
alldefconfig: $(KERNEL_OUT_STAMP)
|
||||
env KCONFIG_NOTIMESTAMP=true \
|
||||
$(MAKE) -C $(KERNEL_SRC) O=$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) alldefconfig
|
||||
|
||||
endif # FULL_KERNEL_BUILD
|
||||
|
||||
## Install it
|
||||
|
||||
ifeq ($(NEEDS_KERNEL_COPY),true)
|
||||
file := $(INSTALLED_KERNEL_TARGET)
|
||||
ALL_PREBUILT += $(file)
|
||||
$(file) : $(KERNEL_BIN) | $(ACP)
|
||||
$(transform-prebuilt-to-target)
|
||||
|
||||
ALL_PREBUILT += $(INSTALLED_KERNEL_TARGET)
|
||||
endif
|
||||
|
||||
.PHONY: kernel
|
||||
kernel: $(INSTALLED_KERNEL_TARGET)
|
@ -0,0 +1,407 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2013-15 The CyanogenMod Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
#
|
||||
# Run repopick.py -h for a description of this utility.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
import argparse
|
||||
import textwrap
|
||||
from xml.etree import ElementTree
|
||||
|
||||
try:
|
||||
# For python3
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
except ImportError:
|
||||
# For python2
|
||||
import imp
|
||||
import urllib2
|
||||
urllib = imp.new_module('urllib')
|
||||
urllib.error = urllib2
|
||||
urllib.request = urllib2
|
||||
|
||||
|
||||
# Verifies whether pathA is a subdirectory (or the same) as pathB
|
||||
def is_subdir(a, b):
|
||||
a = os.path.realpath(a) + '/'
|
||||
b = os.path.realpath(b) + '/'
|
||||
return b == a[:len(b)]
|
||||
|
||||
|
||||
def fetch_query_via_ssh(remote_url, query):
|
||||
"""Given a remote_url and a query, return the list of changes that fit it
|
||||
This function is slightly messy - the ssh api does not return data in the same structure as the HTTP REST API
|
||||
We have to get the data, then transform it to match what we're expecting from the HTTP RESET API"""
|
||||
if remote_url.count(':') == 2:
|
||||
(uri, userhost, port) = remote_url.split(':')
|
||||
userhost = userhost[2:]
|
||||
elif remote_url.count(':') == 1:
|
||||
(uri, userhost) = remote_url.split(':')
|
||||
userhost = userhost[2:]
|
||||
port = 29418
|
||||
else:
|
||||
raise Exception('Malformed URI: Expecting ssh://[user@]host[:port]')
|
||||
|
||||
|
||||
out = subprocess.check_output(['ssh', '-x', '-p{0}'.format(port), userhost, 'gerrit', 'query', '--format=JSON --patch-sets --current-patch-set', query])
|
||||
if not hasattr(out, 'encode'):
|
||||
out = out.decode()
|
||||
reviews = []
|
||||
for line in out.split('\n'):
|
||||
try:
|
||||
data = json.loads(line)
|
||||
# make our data look like the http rest api data
|
||||
review = {
|
||||
'branch': data['branch'],
|
||||
'change_id': data['id'],
|
||||
'current_revision': data['currentPatchSet']['revision'],
|
||||
'number': int(data['number']),
|
||||
'revisions': {patch_set['revision']: {
|
||||
'number': int(patch_set['number']),
|
||||
'fetch': {
|
||||
'ssh': {
|
||||
'ref': patch_set['ref'],
|
||||
'url': 'ssh://{0}:{1}/{2}'.format(userhost, port, data['project'])
|
||||
}
|
||||
}
|
||||
} for patch_set in data['patchSets']},
|
||||
'subject': data['subject'],
|
||||
'project': data['project'],
|
||||
'status': data['status']
|
||||
}
|
||||
reviews.append(review)
|
||||
except:
|
||||
pass
|
||||
args.quiet or print('Found {0} reviews'.format(len(reviews)))
|
||||
return reviews
|
||||
|
||||
|
||||
def fetch_query_via_http(remote_url, query):
|
||||
|
||||
"""Given a query, fetch the change numbers via http"""
|
||||
url = '{0}/changes/?q={1}&o=CURRENT_REVISION&o=ALL_REVISIONS'.format(remote_url, query)
|
||||
data = urllib.request.urlopen(url).read().decode('utf-8')
|
||||
reviews = json.loads(data[5:])
|
||||
|
||||
for review in reviews:
|
||||
review['number'] = review.pop('_number')
|
||||
|
||||
return reviews
|
||||
|
||||
|
||||
def fetch_query(remote_url, query):
|
||||
"""Wrapper for fetch_query_via_proto functions"""
|
||||
if remote_url[0:3] == 'ssh':
|
||||
return fetch_query_via_ssh(remote_url, query)
|
||||
elif remote_url[0:4] == 'http':
|
||||
return fetch_query_via_http(remote_url, query.replace(' ', '+'))
|
||||
else:
|
||||
raise Exception('Gerrit URL should be in the form http[s]://hostname/ or ssh://[user@]host[:port]')
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Default to CyanogenMod Gerrit
|
||||
default_gerrit = 'http://review.cyanogenmod.org'
|
||||
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description=textwrap.dedent('''\
|
||||
repopick.py is a utility to simplify the process of cherry picking
|
||||
patches from CyanogenMod's Gerrit instance (or any gerrit instance of your choosing)
|
||||
|
||||
Given a list of change numbers, repopick will cd into the project path
|
||||
and cherry pick the latest patch available.
|
||||
|
||||
With the --start-branch argument, the user can specify that a branch
|
||||
should be created before cherry picking. This is useful for
|
||||
cherry-picking many patches into a common branch which can be easily
|
||||
abandoned later (good for testing other's changes.)
|
||||
|
||||
The --abandon-first argument, when used in conjunction with the
|
||||
--start-branch option, will cause repopick to abandon the specified
|
||||
branch in all repos first before performing any cherry picks.'''))
|
||||
parser.add_argument('change_number', nargs='*', help='change number to cherry pick. Use {change number}/{patchset number} to get a specific revision.')
|
||||
parser.add_argument('-i', '--ignore-missing', action='store_true', help='do not error out if a patch applies to a missing directory')
|
||||
parser.add_argument('-s', '--start-branch', nargs=1, help='start the specified branch before cherry picking')
|
||||
parser.add_argument('-a', '--abandon-first', action='store_true', help='before cherry picking, abandon the branch specified in --start-branch')
|
||||
parser.add_argument('-b', '--auto-branch', action='store_true', help='shortcut to "--start-branch auto --abandon-first --ignore-missing"')
|
||||
parser.add_argument('-q', '--quiet', action='store_true', help='print as little as possible')
|
||||
parser.add_argument('-v', '--verbose', action='store_true', help='print extra information to aid in debug')
|
||||
parser.add_argument('-f', '--force', action='store_true', help='force cherry pick even if change is closed')
|
||||
parser.add_argument('-p', '--pull', action='store_true', help='execute pull instead of cherry-pick')
|
||||
parser.add_argument('-P', '--path', help='use the specified path for the change')
|
||||
parser.add_argument('-t', '--topic', help='pick all commits from a specified topic')
|
||||
parser.add_argument('-Q', '--query', help='pick all commits using the specified query')
|
||||
parser.add_argument('-g', '--gerrit', default=default_gerrit, help='Gerrit Instance to use. Form proto://[user@]host[:port]')
|
||||
parser.add_argument('-e', '--exclude', nargs=1, help='exclude a list of commit numbers separated by a ,')
|
||||
args = parser.parse_args()
|
||||
if not args.start_branch and args.abandon_first:
|
||||
parser.error('if --abandon-first is set, you must also give the branch name with --start-branch')
|
||||
if args.auto_branch:
|
||||
args.abandon_first = True
|
||||
args.ignore_missing = True
|
||||
if not args.start_branch:
|
||||
args.start_branch = ['auto']
|
||||
if args.quiet and args.verbose:
|
||||
parser.error('--quiet and --verbose cannot be specified together')
|
||||
|
||||
if (1 << bool(args.change_number) << bool(args.topic) << bool(args.query)) != 2:
|
||||
parser.error('One (and only one) of change_number, topic, and query are allowed')
|
||||
|
||||
# Change current directory to the top of the tree
|
||||
if 'ANDROID_BUILD_TOP' in os.environ:
|
||||
top = os.environ['ANDROID_BUILD_TOP']
|
||||
|
||||
if not is_subdir(os.getcwd(), top):
|
||||
sys.stderr.write('ERROR: You must run this tool from within $ANDROID_BUILD_TOP!\n')
|
||||
sys.exit(1)
|
||||
os.chdir(os.environ['ANDROID_BUILD_TOP'])
|
||||
|
||||
# Sanity check that we are being run from the top level of the tree
|
||||
if not os.path.isdir('.repo'):
|
||||
sys.stderr.write('ERROR: No .repo directory found. Please run this from the top of your tree.\n')
|
||||
sys.exit(1)
|
||||
|
||||
# If --abandon-first is given, abandon the branch before starting
|
||||
if args.abandon_first:
|
||||
# Determine if the branch already exists; skip the abandon if it does not
|
||||
plist = subprocess.check_output(['repo', 'info'])
|
||||
if not hasattr(plist, 'encode'):
|
||||
plist = plist.decode()
|
||||
needs_abandon = False
|
||||
for pline in plist.splitlines():
|
||||
matchObj = re.match(r'Local Branches.*\[(.*)\]', pline)
|
||||
if matchObj:
|
||||
local_branches = re.split('\s*,\s*', matchObj.group(1))
|
||||
if any(args.start_branch[0] in s for s in local_branches):
|
||||
needs_abandon = True
|
||||
|
||||
if needs_abandon:
|
||||
# Perform the abandon only if the branch already exists
|
||||
if not args.quiet:
|
||||
print('Abandoning branch: %s' % args.start_branch[0])
|
||||
subprocess.check_output(['repo', 'abandon', args.start_branch[0]])
|
||||
if not args.quiet:
|
||||
print('')
|
||||
|
||||
# Get the master manifest from repo
|
||||
# - convert project name and revision to a path
|
||||
project_name_to_data = {}
|
||||
manifest = subprocess.check_output(['repo', 'manifest'])
|
||||
xml_root = ElementTree.fromstring(manifest)
|
||||
projects = xml_root.findall('project')
|
||||
remotes = xml_root.findall('remote')
|
||||
default_revision = xml_root.findall('default')[0].get('revision')
|
||||
|
||||
#dump project data into the a list of dicts with the following data:
|
||||
#{project: {path, revision}}
|
||||
|
||||
for project in projects:
|
||||
name = project.get('name')
|
||||
path = project.get('path')
|
||||
revision = project.get('revision')
|
||||
if revision is None:
|
||||
for remote in remotes:
|
||||
if remote.get('name') == project.get('remote'):
|
||||
revision = remote.get('revision')
|
||||
if revision is None:
|
||||
revision = default_revision
|
||||
|
||||
if not name in project_name_to_data:
|
||||
project_name_to_data[name] = {}
|
||||
revision = revision.split('refs/heads/')[-1]
|
||||
project_name_to_data[name][revision] = path
|
||||
|
||||
# get data on requested changes
|
||||
reviews = []
|
||||
change_numbers = []
|
||||
if args.topic:
|
||||
reviews = fetch_query(args.gerrit, 'topic:{0}'.format(args.topic))
|
||||
change_numbers = sorted([str(r['number']) for r in reviews])
|
||||
if args.query:
|
||||
reviews = fetch_query(args.gerrit, args.query)
|
||||
change_numbers = sorted([str(r['number']) for r in reviews])
|
||||
if args.change_number:
|
||||
for c in args.change_number:
|
||||
if '-' in c:
|
||||
templist = c.split('-')
|
||||
for i in range(int(templist[0]), int(templist[1]) + 1):
|
||||
change_numbers.append(str(i))
|
||||
else:
|
||||
change_numbers.append(c)
|
||||
reviews = fetch_query(args.gerrit, ' OR '.join('change:{0}'.format(x.split('/')[0]) for x in change_numbers))
|
||||
|
||||
# make list of things to actually merge
|
||||
mergables = []
|
||||
|
||||
# If --exclude is given, create the list of commits to ignore
|
||||
exclude = []
|
||||
if args.exclude:
|
||||
exclude = args.exclude[0].split(',')
|
||||
|
||||
for change in change_numbers:
|
||||
patchset = None
|
||||
if '/' in change:
|
||||
(change, patchset) = change.split('/')
|
||||
|
||||
if change in exclude:
|
||||
continue
|
||||
|
||||
change = int(change)
|
||||
review = next((x for x in reviews if x['number'] == change), None)
|
||||
if review is None:
|
||||
print('Change %d not found, skipping' % change)
|
||||
continue
|
||||
|
||||
mergables.append({
|
||||
'subject': review['subject'],
|
||||
'project': review['project'],
|
||||
'branch': review['branch'],
|
||||
'change_id': review['change_id'],
|
||||
'change_number': review['number'],
|
||||
'status': review['status'],
|
||||
'fetch': None
|
||||
})
|
||||
mergables[-1]['fetch'] = review['revisions'][review['current_revision']]['fetch']
|
||||
mergables[-1]['id'] = change
|
||||
if patchset:
|
||||
try:
|
||||
mergables[-1]['fetch'] = [x['fetch'] for x in review['revisions'] if x['_number'] == patchset][0]
|
||||
mergables[-1]['id'] = '{0}/{1}'.format(change, patchset)
|
||||
except (IndexError, ValueError):
|
||||
args.quiet or print('ERROR: The patch set {0}/{1} could not be found, using CURRENT_REVISION instead.'.format(change, patchset))
|
||||
|
||||
for item in mergables:
|
||||
args.quiet or print('Applying change number {0}...'.format(item['id']))
|
||||
# Check if change is open and exit if it's not, unless -f is specified
|
||||
if (item['status'] != 'OPEN' and item['status'] != 'NEW') and not args.query:
|
||||
if args.force:
|
||||
print('!! Force-picking a closed change !!\n')
|
||||
else:
|
||||
print('Change status is ' + item['status'] + '. Skipping the cherry pick.\nUse -f to force this pick.')
|
||||
continue
|
||||
|
||||
# Convert the project name to a project path
|
||||
# - check that the project path exists
|
||||
project_path = None
|
||||
|
||||
if item['project'] in project_name_to_data and item['branch'] in project_name_to_data[item['project']]:
|
||||
project_path = project_name_to_data[item['project']][item['branch']]
|
||||
elif args.path:
|
||||
project_path = args.path
|
||||
elif args.ignore_missing:
|
||||
print('WARNING: Skipping {0} since there is no project directory for: {1}\n'.format(item['id'], item['project']))
|
||||
continue
|
||||
else:
|
||||
sys.stderr.write('ERROR: For {0}, could not determine the project path for project {1}\n'.format(item['id'], item['project']))
|
||||
sys.exit(1)
|
||||
|
||||
# If --start-branch is given, create the branch (more than once per path is okay; repo ignores gracefully)
|
||||
if args.start_branch:
|
||||
subprocess.check_output(['repo', 'start', args.start_branch[0], project_path])
|
||||
|
||||
# Determine the maximum commits to check already picked changes
|
||||
check_picked_count = 10
|
||||
branch_commits_count = int(subprocess.check_output(['git', 'rev-list', '--count', 'HEAD'], cwd=project_path))
|
||||
if branch_commits_count <= check_picked_count:
|
||||
check_picked_count = branch_commits_count - 1
|
||||
|
||||
# Check if change is already picked to HEAD...HEAD~check_picked_count
|
||||
found_change = False
|
||||
for i in range(0, check_picked_count):
|
||||
output = subprocess.check_output(['git', 'show', '-q', 'HEAD~{0}'.format(i)], cwd=project_path).split()
|
||||
if 'Change-Id:' in output:
|
||||
head_change_id = ''
|
||||
for j,t in enumerate(reversed(output)):
|
||||
if t == 'Change-Id:':
|
||||
head_change_id = output[len(output) - j]
|
||||
break
|
||||
if head_change_id.strip() == item['change_id']:
|
||||
print('Skipping {0} - already picked in {1} as HEAD~{2}'.format(item['id'], project_path, i))
|
||||
found_change = True
|
||||
break
|
||||
if found_change:
|
||||
continue
|
||||
|
||||
# Print out some useful info
|
||||
if not args.quiet:
|
||||
print('--> Subject: "{0}"'.format(item['subject']))
|
||||
print('--> Project path: {0}'.format(project_path))
|
||||
print('--> Change number: {0} (Patch Set {0})'.format(item['id']))
|
||||
|
||||
if 'anonymous http' in item['fetch']:
|
||||
method = 'anonymous http'
|
||||
else:
|
||||
method = 'ssh'
|
||||
|
||||
# Try fetching from GitHub first if using default gerrit
|
||||
if args.gerrit == default_gerrit:
|
||||
if args.verbose:
|
||||
print('Trying to fetch the change from GitHub')
|
||||
|
||||
if args.pull:
|
||||
cmd = ['git pull --no-edit github', item['fetch'][method]['ref']]
|
||||
else:
|
||||
cmd = ['git fetch github', item['fetch'][method]['ref']]
|
||||
if args.quiet:
|
||||
cmd.append('--quiet')
|
||||
else:
|
||||
print(cmd)
|
||||
result = subprocess.call([' '.join(cmd)], cwd=project_path, shell=True)
|
||||
FETCH_HEAD = '{0}/.git/FETCH_HEAD'.format(project_path)
|
||||
if result != 0 and os.stat(FETCH_HEAD).st_size != 0:
|
||||
print('ERROR: git command failed')
|
||||
sys.exit(result)
|
||||
# Check if it worked
|
||||
if args.gerrit != default_gerrit or os.stat(FETCH_HEAD).st_size == 0:
|
||||
# If not using the default gerrit or github failed, fetch from gerrit.
|
||||
if args.verbose:
|
||||
if args.gerrit == default_gerrit:
|
||||
print('Fetching from GitHub didn\'t work, trying to fetch the change from Gerrit')
|
||||
else:
|
||||
print('Fetching from {0}'.format(args.gerrit))
|
||||
|
||||
if args.pull:
|
||||
cmd = ['git pull --no-edit', item['fetch'][method]['url'], item['fetch'][method]['ref']]
|
||||
else:
|
||||
cmd = ['git fetch', item['fetch'][method]['url'], item['fetch'][method]['ref']]
|
||||
if args.quiet:
|
||||
cmd.append('--quiet')
|
||||
else:
|
||||
print(cmd)
|
||||
result = subprocess.call([' '.join(cmd)], cwd=project_path, shell=True)
|
||||
if result != 0:
|
||||
print('ERROR: git command failed')
|
||||
sys.exit(result)
|
||||
# Perform the cherry-pick
|
||||
if not args.pull:
|
||||
cmd = ['git cherry-pick FETCH_HEAD']
|
||||
if args.quiet:
|
||||
cmd_out = open(os.devnull, 'wb')
|
||||
else:
|
||||
cmd_out = None
|
||||
result = subprocess.call(cmd, cwd=project_path, shell=True, stdout=cmd_out, stderr=cmd_out)
|
||||
if result != 0:
|
||||
print('ERROR: git command failed')
|
||||
sys.exit(result)
|
||||
if not args.quiet:
|
||||
print('')
|
@ -0,0 +1,297 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (C) 2012-2013, The CyanogenMod Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import base64
|
||||
import json
|
||||
import netrc
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
try:
|
||||
# For python3
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
except ImportError:
|
||||
# For python2
|
||||
import imp
|
||||
import urllib2
|
||||
import urlparse
|
||||
urllib = imp.new_module('urllib')
|
||||
urllib.error = urllib2
|
||||
urllib.parse = urlparse
|
||||
urllib.request = urllib2
|
||||
|
||||
from xml.etree import ElementTree
|
||||
|
||||
product = sys.argv[1]
|
||||
|
||||
if len(sys.argv) > 2:
|
||||
depsonly = sys.argv[2]
|
||||
else:
|
||||
depsonly = None
|
||||
|
||||
try:
|
||||
device = product[product.index("_") + 1:]
|
||||
except:
|
||||
device = product
|
||||
|
||||
if not depsonly:
|
||||
print("Device %s not found. Attempting to retrieve device repository from CyanogenMod Github (http://github.com/CyanogenMod)." % device)
|
||||
|
||||
repositories = []
|
||||
|
||||
try:
|
||||
authtuple = netrc.netrc().authenticators("api.github.com")
|
||||
|
||||
if authtuple:
|
||||
auth_string = ('%s:%s' % (authtuple[0], authtuple[2])).encode()
|
||||
githubauth = base64.encodestring(auth_string).decode().replace('\n', '')
|
||||
else:
|
||||
githubauth = None
|
||||
except:
|
||||
githubauth = None
|
||||
|
||||
def add_auth(githubreq):
|
||||
if githubauth:
|
||||
githubreq.add_header("Authorization","Basic %s" % githubauth)
|
||||
|
||||
if not depsonly:
|
||||
githubreq = urllib.request.Request("https://api.github.com/search/repositories?q=%s+user:CyanogenMod+in:name+fork:true" % device)
|
||||
add_auth(githubreq)
|
||||
try:
|
||||
result = json.loads(urllib.request.urlopen(githubreq).read().decode())
|
||||
except urllib.error.URLError:
|
||||
print("Failed to search GitHub")
|
||||
sys.exit()
|
||||
except ValueError:
|
||||
print("Failed to parse return data from GitHub")
|
||||
sys.exit()
|
||||
for res in result.get('items', []):
|
||||
repositories.append(res)
|
||||
|
||||
local_manifests = r'.repo/local_manifests'
|
||||
if not os.path.exists(local_manifests): os.makedirs(local_manifests)
|
||||
|
||||
def exists_in_tree(lm, path):
|
||||
for child in lm.getchildren():
|
||||
if child.attrib['path'] == path:
|
||||
return True
|
||||
return False
|
||||
|
||||
# in-place prettyprint formatter
|
||||
def indent(elem, level=0):
|
||||
i = "\n" + level*" "
|
||||
if len(elem):
|
||||
if not elem.text or not elem.text.strip():
|
||||
elem.text = i + " "
|
||||
if not elem.tail or not elem.tail.strip():
|
||||
elem.tail = i
|
||||
for elem in elem:
|
||||
indent(elem, level+1)
|
||||
if not elem.tail or not elem.tail.strip():
|
||||
elem.tail = i
|
||||
else:
|
||||
if level and (not elem.tail or not elem.tail.strip()):
|
||||
elem.tail = i
|
||||
|
||||
def get_default_revision():
|
||||
m = ElementTree.parse(".repo/manifest.xml")
|
||||
d = m.findall('default')[0]
|
||||
r = d.get('revision')
|
||||
return r.replace('refs/heads/', '').replace('refs/tags/', '')
|
||||
|
||||
def get_from_manifest(devicename):
|
||||
try:
|
||||
lm = ElementTree.parse(".repo/local_manifests/roomservice.xml")
|
||||
lm = lm.getroot()
|
||||
except:
|
||||
lm = ElementTree.Element("manifest")
|
||||
|
||||
for localpath in lm.findall("project"):
|
||||
if re.search("android_device_.*_%s$" % device, localpath.get("name")):
|
||||
return localpath.get("path")
|
||||
|
||||
# Devices originally from AOSP are in the main manifest...
|
||||
try:
|
||||
mm = ElementTree.parse(".repo/manifest.xml")
|
||||
mm = mm.getroot()
|
||||
except:
|
||||
mm = ElementTree.Element("manifest")
|
||||
|
||||
for localpath in mm.findall("project"):
|
||||
if re.search("android_device_.*_%s$" % device, localpath.get("name")):
|
||||
return localpath.get("path")
|
||||
|
||||
return None
|
||||
|
||||
def is_in_manifest(projectpath):
|
||||
try:
|
||||
lm = ElementTree.parse(".repo/local_manifests/roomservice.xml")
|
||||
lm = lm.getroot()
|
||||
except:
|
||||
lm = ElementTree.Element("manifest")
|
||||
|
||||
for localpath in lm.findall("project"):
|
||||
if localpath.get("path") == projectpath:
|
||||
return True
|
||||
|
||||
## Search in main manifest, too
|
||||
try:
|
||||
lm = ElementTree.parse(".repo/manifest.xml")
|
||||
lm = lm.getroot()
|
||||
except:
|
||||
lm = ElementTree.Element("manifest")
|
||||
|
||||
for localpath in lm.findall("project"):
|
||||
if localpath.get("path") == projectpath:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def add_to_manifest(repositories, fallback_branch = None):
|
||||
try:
|
||||
lm = ElementTree.parse(".repo/local_manifests/roomservice.xml")
|
||||
lm = lm.getroot()
|
||||
except:
|
||||
lm = ElementTree.Element("manifest")
|
||||
|
||||
for repository in repositories:
|
||||
repo_name = repository['repository']
|
||||
repo_target = repository['target_path']
|
||||
print('Checking if %s is fetched from %s' % (repo_target, repo_name))
|
||||
if is_in_manifest(repo_target):
|
||||
print('CyanogenMod/%s already fetched to %s' % (repo_name, repo_target))
|
||||
continue
|
||||
|
||||
print('Adding dependency: CyanogenMod/%s -> %s' % (repo_name, repo_target))
|
||||
project = ElementTree.Element("project", attrib = { "path": repo_target,
|
||||
"remote": "github", "name": "CyanogenMod/%s" % repo_name })
|
||||
|
||||
if 'branch' in repository:
|
||||
project.set('revision',repository['branch'])
|
||||
elif fallback_branch:
|
||||
print("Using fallback branch %s for %s" % (fallback_branch, repo_name))
|
||||
project.set('revision', fallback_branch)
|
||||
else:
|
||||
print("Using default branch for %s" % repo_name)
|
||||
|
||||
lm.append(project)
|
||||
|
||||
indent(lm, 0)
|
||||
raw_xml = ElementTree.tostring(lm).decode()
|
||||
raw_xml = '<?xml version="1.0" encoding="UTF-8"?>\n' + raw_xml
|
||||
|
||||
f = open('.repo/local_manifests/roomservice.xml', 'w')
|
||||
f.write(raw_xml)
|
||||
f.close()
|
||||
|
||||
def fetch_dependencies(repo_path, fallback_branch = None):
|
||||
print('Looking for dependencies')
|
||||
dependencies_path = repo_path + '/cm.dependencies'
|
||||
syncable_repos = []
|
||||
|
||||
if os.path.exists(dependencies_path):
|
||||
dependencies_file = open(dependencies_path, 'r')
|
||||
dependencies = json.loads(dependencies_file.read())
|
||||
fetch_list = []
|
||||
|
||||
for dependency in dependencies:
|
||||
if not is_in_manifest(dependency['target_path']):
|
||||
fetch_list.append(dependency)
|
||||
syncable_repos.append(dependency['target_path'])
|
||||
|
||||
dependencies_file.close()
|
||||
|
||||
if len(fetch_list) > 0:
|
||||
print('Adding dependencies to manifest')
|
||||
add_to_manifest(fetch_list, fallback_branch)
|
||||
else:
|
||||
print('Dependencies file not found, bailing out.')
|
||||
|
||||
if len(syncable_repos) > 0:
|
||||
print('Syncing dependencies')
|
||||
os.system('repo sync --force-sync %s' % ' '.join(syncable_repos))
|
||||
|
||||
for deprepo in syncable_repos:
|
||||
fetch_dependencies(deprepo)
|
||||
|
||||
def has_branch(branches, revision):
|
||||
return revision in [branch['name'] for branch in branches]
|
||||
|
||||
if depsonly:
|
||||
repo_path = get_from_manifest(device)
|
||||
if repo_path:
|
||||
fetch_dependencies(repo_path)
|
||||
else:
|
||||
print("Trying dependencies-only mode on a non-existing device tree?")
|
||||
|
||||
sys.exit()
|
||||
|
||||
else:
|
||||
for repository in repositories:
|
||||
repo_name = repository['name']
|
||||
if repo_name.startswith("android_device_") and repo_name.endswith("_" + device):
|
||||
print("Found repository: %s" % repository['name'])
|
||||
|
||||
manufacturer = repo_name.replace("android_device_", "").replace("_" + device, "")
|
||||
|
||||
default_revision = get_default_revision()
|
||||
print("Default revision: %s" % default_revision)
|
||||
print("Checking branch info")
|
||||
githubreq = urllib.request.Request(repository['branches_url'].replace('{/branch}', ''))
|
||||
add_auth(githubreq)
|
||||
result = json.loads(urllib.request.urlopen(githubreq).read().decode())
|
||||
|
||||
## Try tags, too, since that's what releases use
|
||||
if not has_branch(result, default_revision):
|
||||
githubreq = urllib.request.Request(repository['tags_url'].replace('{/tag}', ''))
|
||||
add_auth(githubreq)
|
||||
result.extend (json.loads(urllib.request.urlopen(githubreq).read().decode()))
|
||||
|
||||
repo_path = "device/%s/%s" % (manufacturer, device)
|
||||
adding = {'repository':repo_name,'target_path':repo_path}
|
||||
|
||||
fallback_branch = None
|
||||
if not has_branch(result, default_revision):
|
||||
if os.getenv('ROOMSERVICE_BRANCHES'):
|
||||
fallbacks = list(filter(bool, os.getenv('ROOMSERVICE_BRANCHES').split(' ')))
|
||||
for fallback in fallbacks:
|
||||
if has_branch(result, fallback):
|
||||
print("Using fallback branch: %s" % fallback)
|
||||
fallback_branch = fallback
|
||||
break
|
||||
|
||||
if not fallback_branch:
|
||||
print("Default revision %s not found in %s. Bailing." % (default_revision, repo_name))
|
||||
print("Branches found:")
|
||||
for branch in [branch['name'] for branch in result]:
|
||||
print(branch)
|
||||
print("Use the ROOMSERVICE_BRANCHES environment variable to specify a list of fallback branches.")
|
||||
sys.exit()
|
||||
|
||||
add_to_manifest([adding], fallback_branch)
|
||||
|
||||
print("Syncing repository to retrieve project.")
|
||||
os.system('repo sync --force-sync %s' % repo_path)
|
||||
print("Repository synced!")
|
||||
|
||||
fetch_dependencies(repo_path, fallback_branch)
|
||||
print("Done")
|
||||
sys.exit()
|
||||
|
||||
print("Repository for %s not found in the CyanogenMod Github repository list. If this is in error, you may need to manually add it to your local_manifests/roomservice.xml." % device)
|
Loading…
Reference in new issue