In my Makefile, I know the path of directory, and need to rollback of directory.
Here is my work case:
I am writing the Android makefile, following is some code:
LOCAL_PATH :=$(call my-dir) #this will get the path that Android.mk locate.
...
LOCAL_MODULE := mymod
LOCAL_SRC_FILES := /tmp/mymod.ko
include $(BUILD_PREBUILT)
.....
According to Android prebuild system(which implemented in build/core/prebuild.mk), this will copy the $(LOCAL_PATH)/tmp/mymod.ko to the destination($(LOCAL_PATH)added by prebuid.mk), but I want to locate the mymod.ko just to /tmp, so I have to add some ../../../ to my LOCAL_SRC_FILES, that I can remove the $(LOCAL_PATH).
that is, I need replace $(LOCAL_PATH) to some ../../..
You could try something like this:
empty :=
spaces := $(empty) $(empty)
to-root = $(subst $(space),/,$(patsubst %,..,$(subst /,$(space),$1)))
# Test
$(info aaa/bbb/ccc -> $(call to-root,aaa/bbb/ccc))
This will break if one of the path components contains a space, but make cannot handle those very well anyway.
Related
I have a variable (which typically reflects the target's name) in one of the following two forms (with and without extension)
BUILD_DIR/DIR1/DIR2/DIR3/A
BUILD_DIR/DIR1/DIR2/DIR3/B.ext
For a give variable I would like to add another layer (DIR0) under BUILD_DIR and add/change .ext to .new_ext.
So that the variables above are both transformed into
BUILD_DIR/DIR0/DIR1/DIR2/DIR3/A.new_ext
BUILD_DIR/DIR0/DIR1/DIR2/DIR3/B.new_ext
In other words DIR0 is added right after BUILD_DIR and extension is changed if it was present and added if not.
Having a function in the Makefile that does the job should also be sufficient.
Assuming the paths are in a variable such as...
PATHS := BUILD_DIR/DIR1/DIR2/DIR3/A BUILD_DIR/DIR1/DIR2/DIR3/B.ext
Then try something like...
EXTRA_DIR := DIR0
NEW_EXTENSION := new_ext
PATHS := $(addsuffix .$(NEW_EXTENSION),$(patsubst %.ext,%,$(patsubst BUILD_DIR/%,BUILD_DIR/$(EXTRA_DIR)/%,$(PATHS))))
Here is a solution that seems to be the shortest among presented so far
FUNC = $(patsubst $(2)/%,$(2)/$(DIR0)/%.new_ext,$(1:%.ext=%))
$(call FUNC,$(VARIABLE),$(BUILD_DIR))
I have a Android native application which builds for platform x86, armeabi and armeabi-v7a. Now depending upon whether the platform is x86 or arm, I need to run the script accordingly with the corresponding arguments so appropriate third party tool environment variables are set. I tried doing below:
.o.cpp:
ifeq ($(TARGET_ARCH),x86)
$(info $(shell ($(CACHE_LOCAL_PATH_MAIN)/setup_tool.sh x86)))
else
$(info $(shell ($(CACHE_LOCAL_PATH_MAIN)/setup_tool.sh arm)))
endif
But the problem is, when the makefile is parsed, these scripts get run in the initial phase itself 3 times and not before compilation of every platform begins. Is there a way to get this fixed so the script gets run just before the compilation for every platform begins? Thanks.
UPDATED with Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := \ <path_to_include_files>
LOCAL_CFLAGS := <cflags included here>
LOCAL_LDLIBS := <ld libs included here>
LOCAL_SRC_FILES := <src files to be compiled>
LOCAL_MODULE := <module_name>
LOCAL_SHARED_LIBRARIES := <shared libs on which we are dependent>
LOCAL_WHOLE_STATIC_LIBRARIES := <static libs>
include $(BUILD_SHARED_LIBRARY)
A simple, but not elegant solution is as follows:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := \ <path_to_include_files>
LOCAL_CFLAGS := <cflags included here>
LOCAL_LDLIBS := <ld libs included here>
ifeq ($(TARGET_ARCH),x86)
LOCAL_SRC_FILES := /tmp/dummy.x86.c
else
LOCAL_SRC_FILES := /tmp/dummy.arm.c
$(info $(shell ($(CACHE_LOCAL_PATH_MAIN)/setup_tool.sh arm)))
endif
LOCAL_SRC_FILES += <src files to be compiled>
LOCAL_MODULE := <module_name>
LOCAL_SHARED_LIBRARIES := <shared libs on which we are dependent>
LOCAL_WHOLE_STATIC_LIBRARIES := <static libs>
include $(BUILD_SHARED_LIBRARY)
.PHONY: /tmp/dummy.x86.c /tmp/dummy.arm.c
/tmp/dummy.x86.c:
$(CACHE_LOCAL_PATH_MAIN)/setup_tool.sh x86
#touch $#
/tmp/dummy.arm.c:
$(CACHE_LOCAL_PATH_MAIN)/setup_tool.sh arm
#touch $#
One caveat: this will link the library every time, even if nothing changed. You can set dependencies carefully instead of .PHONY to improve this.
Given a previously defined variable $(LOCAL_SRC_FILES), how can I remove every file that's under directory .AppleDouble. Note that there can be multiple .AppleDouble directories in various location in source tree.
I tried:
LOCAL_SRC_FILES := $(filter-out %.AppleDouble%, $(LOCAL_SRC_FILES))
which doesn't seem work.
Thanks.
Something like this might work:
LOCAL_SRC_FILES := $(foreach f,$(LOCAL_SRC_FILES),$(if $(findstring .AppleDouble,$f),,$f))
For directories that are exactly .AppleDouble I think you want this:
LOCAL_SRC_FILES := $(foreach f,$(LOCAL_SRC_FILES),$(if $(filter .AppleDouble,$(subst /, ,$f)),,$f))
findstring is unfortunately indiscriminate in its matching. It doesn't care about word boundaries or anything.
I am currently have an Android.mk file. For some requirement I need to write a standard GNU make file to build the same program.
As you know in Android native build, we simply put all source files together like
LOCAL_SRC_FILES := a.c b.c d.cpp e.cpp
Now I want to do something in Makefile like:
OBJ = $(LOCAL_SRC_FILES: .c=.o)
This will only transform .c files with .o object targets. How can I combine the condition ".c or .cpp" together?
I think I am too busy to forget that I can just achieve this target by execute this function twice.
TMP_OBJ = $(LOCAL_SRC_FILES: .c=.o)
OBJ = $(TMP_OBJ: .cpp=.o)
Sorry for this silly question.
You could use basename:
OBJ := $(addsuffix .o,$(basename $(LOCAL_SRC_FILES)))
(strips off the suffix of each file in LOCAL_SRC_FILES then adds .o to the end)
Doing it in two steps:
SRC := main.c hello.cpp
OBJ := $(SRC:.c=.o)
OBJ := $(OBJ:.cpp=.o)
I'm trying to consolidate some build information by using a common makefile. My problem is that I want to use that makefile from different subdirectory levels, which makes the working directory value (pwd) unpredictable. For example:
# Makefile.common
TOP := $(shell pwd)
COMPONENT_DIR := $(TOP)/component
COMPONENT_INC := $(COMPONENT_DIR)/include
COMPONENT_LIB := $(COMPONENT_DIR)/libcomponent.a
If I include Makefile.common from a subdirectory, like so, the $(TOP) directory is incorrect and everything else follows suit:
# other_component/Makefile
include ../Makefile.common
# $(COMPONENT_LIB) is incorrectly other_component/component
What's the best way to get Makefile.common to use its own directory path instead of the more fickle pwd?
You should be able to use the MAKEFILE_LIST variable, like this:
# This must be the first line in Makefile.common
TOP := $(dir $(firstword $(MAKEFILE_LIST)))
From the documentation:
As make reads various makefiles, including any obtained from the MAKEFILES variable, the command line, the default files, or from include directives, their names will be automatically appended to the MAKEFILE_LIST variable. They are added right before make begins to parse them. This means that if the first thing a makefile does is examine the last word in this variable, it will be the name of the current makefile. Once the current makefile has used include, however, the last word will be the just-included makefile.
Try this:
ROOT_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
Edit: Be sure to use := instead of = because the latter causes make to use late-binding and MAKEFILE_LIST may have changed due to later includes.
Have you tried doing:
# Makefile.common
TOP ?= $(shell pwd)
COMPONENT_DIR := $(TOP)/component
COMPONENT_INC := $(COMPONENT_DIR)/include
COMPONENT_LIB := $(COMPONENT_DIR)/libcomponent.a
# other_component/Makefile
TOP ?= ..
include ../Makefile.common
Using the ?= construct will keep TOP from being redefined if it is already set. You can set it to the appropriate value based on where you are in the tree when you invoke make. I confess it's been awhile since I've used GNU make so this may not work or may need some tweaks.
My solution:
cwd := $(shell readlink -en $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))))
This also works for calls like make -f /opt/some/dir/Makefile whenn your in /opt/other/path/subdir.
write the common stuff in common.mk. Then put the common.mk in the default directories that Make looks for when it encounters an include statement. See the manual for common directories Make looks for.
You could also put the common.mk in custom directory, and then type make -I customdir.
Inside the Makefile in each subfolder, you do
include common.mk
That is all. No need to worry about path and moving things around.