Following this guide on CM Wiki, I've been compiling CM for my own devices for more than a year now, but that does nothing more than recreating nightly builds. I always wanted to venture beyond the basics and today I got my hands on making some first steps.
What I'm planning to do right now is to customize /system/build.prop prior to building, as opposed to modifying it after flashing. I did some research and identified some scripts and makefiles responsible for generating it, and the one makefile in question is vendor/cm/config/common.mk. The section I'm looking to modify alters the "CyanogenMod version" field displayed in Settings-About, as in the pic below:
common.mk has these lines corresponding to it (slightly modified to shorten):
ifeq ($(CM_BUILDTYPE), RELEASE)
ifndef TARGET_VENDOR_RELEASE_BUILD_ID
CM_VERSION := $(PRODUCT_VERSION_MAJOR).$(PRODUCT_VERSION_MINOR).$(PRODUCT_VERSION_MAINTENANCE)$(PRODUCT_VERSION_DEVICE_SPECIFIC)-$(CM_BUILD)
else
ifeq ($(TARGET_BUILD_VARIANT),user)
ifeq ($(CM_VERSION_MAINTENANCE),0)
CM_VERSION := $(PRODUCT_VERSION_MAJOR).$(PRODUCT_VERSION_MINOR)-$(TARGET_VENDOR_RELEASE_BUILD_ID)-$(CM_BUILD)
else
CM_VERSION := $(PRODUCT_VERSION_MAJOR).$(PRODUCT_VERSION_MINOR).$(CM_VERSION_MAINTENANCE)-$(TARGET_VENDOR_RELEASE_BUILD_ID)-$(CM_BUILD)
endif
else
CM_VERSION := $(PRODUCT_VERSION_MAJOR).$(PRODUCT_VERSION_MINOR).$(PRODUCT_VERSION_MAINTENANCE)$(PRODUCT_VERSION_DEVICE_SPECIFIC)-$(CM_BUILD)
endif
endif
else
ifeq ($(CM_VERSION_MAINTENANCE),0)
CM_VERSION := $(PRODUCT_VERSION_MAJOR).$(PRODUCT_VERSION_MINOR)-$(shell date -u +%Y%m%d)-$(CM_BUILDTYPE)$(CM_EXTRAVERSION)-$(CM_BUILD)
else
CM_VERSION := $(PRODUCT_VERSION_MAJOR).$(PRODUCT_VERSION_MINOR).$(CM_VERSION_MAINTENANCE)-$(shell date -u +%Y%m%d)-$(CM_BUILDTYPE)$(CM_EXTRAVERSION)-$(CM_BUILD)
endif
endif
PRODUCT_PROPERTY_OVERRIDES += \
ro.cm.version=$(CM_VERSION) \
ro.cm.releasetype=$(CM_BUILDTYPE) \
ro.modversion=$(CM_VERSION) \
ro.cm.display.version=$(CM_VERSION)
Now I want to define another variable with space that stores the custom string that I want to display in that field, for example "CM13 FOO BAR", so I'd write this:
ifndef CM_VERSION_CUSTOM
CM_VERSION_CUSTOM := CM13 FOO BAR
endif
...and assign CM_VERSION_CUSTOM to where CM_VERSION applies.
In practise this doesn't work at all - the string was outputted to /build.prop incorrectly, sometimes as if each space is a newline, sometimes as if the contents after the 1st space doesn't exist, like this:
ro.cm.version=CM13
FOO
BAR
ro.modversion=CM13
ro.cm.display.version=CM13
I tried adding quotes (' and " tested), either to the string definition or to where CM_VERSION CUSTOM was referenced (like "$(CM_VERSION_CUSTOM)"), but none helped. I'm not familiar with makefile at all, so I'm at a loss right now. Can someone point me in the right way?
I ended up just writing a shell script for the purpose. I package the script inside a flashable zip and let updater-script call the script. The script itself goes something like this:
#!/sbin/sh
CM_VER="CyanogenMod 12.1 Nightly CGMod"
sed -i "s/ro.cm.version=.*/ro.cm.version=$CM_VER/g" /system/build.prop
This not only allows me to modify this property, but also others like build type, date and others (with the help of grep) that are hard to touch before building.
Related
I have a makefile that deploys x project in aws
The goal is to execute the make like this:
make deploy-production
And see output like this
Please select the project:
1) api
2) web
3) somethingelse
You press then the number and make continues, by assigning the choice to a variable named project
I have already "autogenerating" targets for supported envs, just want to build the multichoice for projects.
Sample makefile of mine with removed nonrelevant stuff:
ENVIRONMENTS := development staging production
TARGETS := $(foreach X,$(ENVIRONMENTS),deploy-$X)
$(TARGETS):
$(eval ENV:=$(subst deploy-,,$(#)))
# here want to ask for project, env i have already as resolved from above line
Well, make can run any shell script. So if you write a shell script that will ask the user for input and accept an answer you can run it from make.
You could do something like this:
deploy-production:
#echo Please select the project:; \
echo '1) api'; \
echo '2) web'; \
echo '3) somethingelse'; \
read -p 'Enter value: ' result && $(MAKE) CHOICE=$$result got-choice
There is a LOT left out here: handling invalid values, converting the CHOICE value into a target that would then be a prerequisite of the got-choice target, etc. etc. I don't really think this is a good way forward but you could make it work.
I am new to GNUmake.
I have a requirement to replace the file paths based on certain condition.
TARGET_EXCEPTION := /home/ip/lib_build
TGT_TOOLS := /demo/build/new_project
ifdef SET_BUILD
ifneq (0,$(RELEASE))
FILES += $(addprefix $(TARGET_EXCEPTION)/tools/test/,$(subst $(TGTTOOLS)/tools/test/,,$(RELEASE_FILES)))
endif
endif
RELEASE_FILES variable has multiple file paths assigned. Out of those files i am interested only in folders with $(TGT_TOOLS)/tools/test/ and replace it with $(TARGET_EXCEPTION)/tools/test/.. Is there anything wrong in my above code? Please help!
I have a requirement to replace the file paths based on certain condition.
I daresay the actual requirement is probably more like "the tests should be installed in the directory named by $(TARGET_EXCEPTION) in a release build, but in the directory named by $(TGT_TOOLS) otherwise. The distinction is important, because it is clearer and more portable to just assign the path appropriately in the first place.
That might look something like this:
# Possible test install locations
TARGET_EXCEPTION := /home/ip/lib_build
TGT_TOOLS := /demo/build/new_project
####
#
# Determine which location to use
#
ifdef SET_BUILD
TEST_INSTALL_RELEASE := $(RELEASE)
else
TEST_INSTALL_RELEASE := 0
endif
ifneq (0,$(TEST_INSTALL_RELEASE))
TEST_DIR := $(TARGET_EXCEPTION)
else
TEST_DIR := $(TGT_TOOLS)
endif
#
####
# Define the release files in the desired location from the start
RELEASE_FILES := \
# ...
$(TEST_DIR)/tools/test/test1 \
$(TEST_DIR)/tools/test/test2 \
# ...
# No substitution needed; the targets are already named correctly
FILES += $(RELEASE_FILES)
Is there anything wrong in my above code?
It attempts to implement a poor approach. Also, it very well might not interoperate as you require with your makefile's rules related to the affected files. The above might also have the latter problem, but in that case there is also a clear solution: refer to the affected files everywhere by the name format given in the example.
I am trying to optimize our build targets. In our current process we have separate targets for 32bit & 64bit build. Due to separate targets we have hundreds of targets in our build flow. Where we try to make it global i.e. one target for both 32-bit and 64-bit build. I'm trying to achieve this with the code below.
Target/Output directory for 32-bit build should be like:
/test/scratch/<client_name>/Linux/...
Target/Output directory for 64-bit build should be like:
/test/scratch/<client_name>/Linux-64bit/...
So based on above Target directory paths I am searching the string Linux using $(findstring) function and proceed with 32-bit command to run. Else it will run 64bit command as shown below.
RELEASE_FILES := $(TARGET_DIR)/build/test/csimtime.c
$(RELEASE_FILES): $(TGTDIRFILES)/%: %
ifneq (Linux,$(findstring $(OS),$#))
$(test_lib_32)
else
$(test_lib_64)
endif
$(TARGET_DIR) variable is passed as parameter to make command
make TARGET_DIR=$(TGT32) all32
For 64-bit we will pass TARGET_DIR=$(TGT64) instead.
Note: test_lib_32/64 above are macro definition in other make file which we are including in current make file.
It works fine as expected, But I am not sure whether this is the best way? And I notice one problem here, Generally TGT32/TGT64 variable which we are passing has values either:
/test/scratch/<client_name>/Linux/ (for 32bit)
or
/test/scratch/<client_name>/Linux-64bit/... (for 64bit)
If someone creates a client with client_name 'Linux' string it wont work. It will always go to if block and try to run 32-bit command even when we run 64-bit build. How can I handle this?
I am looking for getting the string after 'client_name' in above path.. Could please help?
If your target directory name is always something like:
/test/scratch/<client_name>/Linux/...
and there is no / character and no spaces in <client-name>, you can base your test on the exact position of Linux (or Linux-64bit) in the path:
TYPE := $(word 4,$(subst /, ,$(TARGET_DIR)))
ifeq ($(TYPE),Linux)
<something>
else ifeq ($(TYPE),Linux-64bit)
<something-else>
else
$(error Unknown type: $(TYPE))
endif
EDIT if the position is not constant but you know what <client-name> is, and there is no / character and no spaces in <client-name>, you can extract the name of the directory that follows <client-name> in $(TARGET_DIR) like this:
TAIL := $(subst /, ,$(TARGET_DIR))
$(foreach w,$(TAIL),$(eval TAIL := $(wordlist 2,$(words $(TAIL)),$(TAIL)))$(if $(patsubst $(CLIENT_NAME),,$(w)),,$(eval TYPE := $(word 1,$(TAIL)))))
all:
#printf 'TYPE = $(TYPE)\n'
Demo:
$ make TARGET_DIR=/a/b/test-client/Linux/c/d CLIENT_NAME=test-client
TYPE = Linux
$ make TARGET_DIR=/a/b/c/d/test-client/Linux-64bit/e/f/g CLIENT_NAME=test-client
TYPE = Linux-64bit
Explanation:
TAIL := $(subst /, ,$(TARGET_DIR)) replaces the / characters in $(TARGET_DIR) by one space, such that it becomes a list of words (one per directory in the path), and assigns the result to variable TAIL.
$(foreach w,$(TAIL),...) evaluates ... with variable w set successively to each word of $(TAIL).
$(eval TAIL := $(wordlist 2,$(words $(TAIL)),$(TAIL))) re-assigns variable TAIL by removing the leading word.
$(if $(patsubst $(CLIENT_NAME),,$(w)),,...) evaluates ... if $(w) equals $(CLIENT_NAME).
$(eval TYPE := $(word 1,$(TAIL))) assigns the first word of $(TAIL) to variable TYPE.
There may be simpler ways to do the same...
If I understand your question correctly then you get problems with the following $(TARGET_DIR) value:
/.../Linux/.../Linux-64bit
The problem is that you are testing on the value of $#:
/.../Linux/.../Linux-64bit/some/other/file
As you can see that makes it impossible to decide which Linux in the path should be used for the decision.
I would suggest to try this instead:
# if $(TARGET_DIR) ends with /Linux -> 32-bit build
$(RELEASE_FILES): $(TGTDIRFILES)/%: %
ifneq ($(filter %/Linux,$(TARGET_DIR)),)
$(test_lib_32)
else
$(test_lib_64)
endif
I am trying to have a Makefile which is able to use different instances of g++ based on whether I give along a certain target or not. So: If I run make home I want CC to be the g++ executable in /usr/bin, and otherwise in some long path <longpath>/bin.
So I tried checking for my target:
ifeq ("$(TARGET)", "home")
GCCPATH = /usr
HSPARG = home
endif
$(info "$(TARGET)")
$(info "$#")
GCCPATH ?= <longpath>
CC = $(GCCPATH)/bin/g++
GCCLIBPATH = $(GCCPATH)/lib64
However, the outcome of this is:
$ make home
""
""
<further build information>
and GCCPATH is in all occasions equal to <longpath>.
Now my questions are:
1. What do I do wrong?
2. How to fix it?
First of all, make home doesn't set TARGET to home. So you have to execute make TARGET='home' to set it.
Secondly, make cares about spaces, including spaces after commas. So when you wrote ifeq ("$(TARGET)", "home"), make didn't toss away the space after the comma like you might have expected. So what make ended up comparing was "home" and " home".
You can see this by running make TARGET=' home' and seeing what you get. Remove that space and you'll fix the problem.
That said all your quoting isn't doing anything for make either. It doesn't generally care. Quotes are just literal characters to make in almost all places (except in ifeq "arg1" "arg2" cases, etc. and maybe one or two other places but I can't think of any offhand), so you don't need them in the calls to $(info) or even in your ifeq test since you are using the ifeq (arg1,arg2) version.
I am having trouble with some make variables, I have something like this:
SUFFIX := raw
FILENAME = name.$(SUFFIX)
...
...
#much later, in a different makefile far away:
SUFFIX := img
echo $(FILENAME)
But FILENAME has the original raw suffix value (name.raw), not the more recently assigned "img" value.
Am I missing something simple here? Using latest released gmake.
I cannot reproduce this error with a series of includes; there is something else involved. I suggest you try the following and tell us the results:
#echo filename: $(FILENAME)
#echo origin: $(origin FILENAME)
#echo flavor: $(flavor FILENAME)
EDIT:
All right, now we know that FILENAME is being defined simply (i.e. with :=) somewhere. So try to trace the include chain, and find out where that happens. Here's a trick: put these lines in any makefile you're interested in
ifeq ($(flavor FILENAME),simple)
$(warning FILENAME is simply defined)
endif