|  | ;;; android-common.el --- Common functions/variables to dev Android in Emacs. | 
|  | ;; | 
|  | ;; Copyright (C) 2009 The Android Open Source 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. | 
|  |  | 
|  | ;;; Commentary: | 
|  | ;; | 
|  | ;; Variables to customize and common functions for the Android build | 
|  | ;; support in Emacs. | 
|  | ;; There should be no interactive function in this module. | 
|  | ;; | 
|  | ;; You need to have a proper buildspec.mk file in your root directory | 
|  | ;; for this module to work (see $TOP/build/buildspec.mk.default). | 
|  | ;; If the path the product's files/image uses an a product alias, you | 
|  | ;; need to add a mapping in `android-product-alias-map'. For instance | 
|  | ;; if TARGET_PRODUCT is foo but the build directory is out/target/product/bar, | 
|  | ;; you need to add a mapping Target:foo -> Alias:bar | 
|  | ;; | 
|  |  | 
|  | ;;; Code: | 
|  |  | 
|  | (defgroup android nil | 
|  | "Support for android development in Emacs." | 
|  | :prefix "android-"                    ; Currently unused. | 
|  | :tag    "Android" | 
|  | :group  'tools) | 
|  |  | 
|  | ;;;###autoload | 
|  | (defcustom android-compilation-jobs 2 | 
|  | "Number of jobs used to do a compilation (-j option of make)." | 
|  | :type 'integer | 
|  | :group 'android) | 
|  |  | 
|  | ;;;###autoload | 
|  | (defcustom android-compilation-no-buildenv-warning t | 
|  | "If not nil, suppress warnings from the build env (Makefile, | 
|  | bash) from the compilation output since they interfere with | 
|  | `next-error'." | 
|  | :type 'boolean | 
|  | :group 'android) | 
|  |  | 
|  | ;;;###autoload | 
|  | (defcustom android-product-alias-map nil | 
|  | "Alist between product targets (declared in buildspec.mk) and actual | 
|  | product build directory used by `android-product'. | 
|  |  | 
|  | For instance if TARGET_PRODUCT is 'foo' but the build directory | 
|  | is 'out/target/product/bar', you need to add a mapping Target:foo -> Alias:bar." | 
|  | :type '(repeat (list (string :tag "Target") | 
|  | (string :tag "Alias"))) | 
|  | :group 'android) | 
|  |  | 
|  | (defconst android-output-buffer-name "*Android Output*" | 
|  | "Name of the default buffer for the output of the commands. | 
|  | There is only one instance of such a buffer.") | 
|  |  | 
|  | (defun android-find-build-tree-root () | 
|  | "Ascend the current path until the root of the android build tree is found. | 
|  | Similarly to the shell functions in envsetup.sh, for the root both ./Makefile | 
|  | and ./build/core/envsetup.mk are exiting files. | 
|  | Return the root of the build tree.  Signal an error if not found." | 
|  | (let ((default-directory default-directory)) | 
|  | (while (and (> (length default-directory) 2) | 
|  | (not (file-exists-p (concat default-directory | 
|  | "Makefile"))) | 
|  | (not (file-exists-p (concat default-directory | 
|  | "build/core/envsetup.mk")))) | 
|  | (setq default-directory | 
|  | (substring default-directory 0 | 
|  | (string-match "[^/]+/$" default-directory)))) | 
|  | (if (> (length default-directory) 2) | 
|  | default-directory | 
|  | (error "Not in a valid android tree")))) | 
|  |  | 
|  | (defun android-project-p () | 
|  | "Return nil if not in an android build tree." | 
|  | (condition-case nil | 
|  | (android-find-build-tree-root) | 
|  | (error nil))) | 
|  |  | 
|  | (defun android-host () | 
|  | "Return the <system>-<arch> string (e.g linux-x86). | 
|  | Only linux and darwin on x86 architectures are supported." | 
|  | (or (string-match "x86" system-configuration) | 
|  | (string-match "i386" system-configuration) | 
|  | (error "Unknown arch")) | 
|  | (or (and (string-match "darwin" system-configuration) "darwin-x86") | 
|  | (and (string-match "linux" system-configuration) "linux-x86") | 
|  | (error "Unknown system"))) | 
|  |  | 
|  | (defun android-product () | 
|  | "Return the product built according to the buildspec.mk. | 
|  | You must have buildspec.mk file in the top directory. | 
|  |  | 
|  | Additional product aliases can be listed in `android-product-alias-map' | 
|  | if the product actually built is different from the one listed | 
|  | in buildspec.mk" | 
|  | (save-excursion | 
|  | (let* ((buildspec (concat (android-find-build-tree-root) "buildspec.mk")) | 
|  | (product (with-current-buffer (find-file-noselect buildspec) | 
|  | (goto-char (point-min)) | 
|  | (search-forward "TARGET_PRODUCT:=") | 
|  | (buffer-substring-no-properties (point) | 
|  | (scan-sexps (point) 1)))) | 
|  | (alias (assoc product android-product-alias-map))) | 
|  | ; Post processing, adjust the names. | 
|  | (if (not alias) | 
|  | product | 
|  | (nth 1 alias))))) | 
|  |  | 
|  | (defun android-product-path () | 
|  | "Return the full path to the product directory. | 
|  |  | 
|  | Additional product aliases can be added in `android-product-alias-map' | 
|  | if the product actually built is different from the one listed | 
|  | in buildspec.mk" | 
|  | (let ((path (concat (android-find-build-tree-root) "out/target/product/" | 
|  | (android-product)))) | 
|  | (when (not (file-exists-p path)) | 
|  | (error (format "%s does not exist. If product %s maps to another one, | 
|  | add an entry to android-product-map." path (android-product)))) | 
|  | path)) | 
|  |  | 
|  | (defun android-find-host-bin (binary) | 
|  | "Return the full path to the host BINARY. | 
|  | Binaries don't depend on the device, just on the host type. | 
|  | Try first to locate BINARY in the out/host tree.  Fallback using | 
|  | the shell exec PATH setup." | 
|  | (if (android-project-p) | 
|  | (let ((path (concat (android-find-build-tree-root) "out/host/" | 
|  | (android-host) "/bin/" binary))) | 
|  | (if (file-exists-p path) | 
|  | path | 
|  | (error (concat binary " is missing.")))) | 
|  | (executable-find binary))) | 
|  |  | 
|  | (defun android-adb () | 
|  | "Return the path to the adb executable. | 
|  | If not in the build tree use the PATH env variable." | 
|  | (android-find-host-bin "adb")) | 
|  |  | 
|  | (defun android-fastboot () | 
|  | "Return the path to the fastboot executable. | 
|  | If not in the build tree use the PATH env variable." | 
|  | ; For fastboot -p is the name of the product, *not* the full path to | 
|  | ; its directory like adb requests sometimes. | 
|  | (concat (android-find-host-bin "fastboot") " -p " (android-product))) | 
|  |  | 
|  | (defun android-adb-command (command &optional product) | 
|  | "Execute 'adb COMMAND'. | 
|  | If the optional PRODUCT is not nil, -p (android-product-path) is used | 
|  | when adb is invoked." | 
|  | (when (get-buffer android-output-buffer-name) | 
|  | (with-current-buffer android-output-buffer-name | 
|  | (erase-buffer))) | 
|  | (if product | 
|  | (shell-command (concat (android-adb) " -p " (android-product-path) | 
|  | " " command) | 
|  | android-output-buffer-name) | 
|  | (shell-command (concat (android-adb) " " command) | 
|  | android-output-buffer-name))) | 
|  |  | 
|  | (defun android-adb-shell-command (command) | 
|  | "Execute 'adb shell COMMAND'." | 
|  | (android-adb-command (concat " shell " command) | 
|  | android-output-buffer-name)) | 
|  |  | 
|  | (provide 'android-common) | 
|  |  | 
|  | ;;; android-common.el ends here |