How to run custom rule in Android.mk before compilation?

http://stackoverflow.com/questions/12372500/how-to-run-custom-rule-in-android-mk-before-compilation

How to run custom rule in Android.mk before compilation?

 

11 down vote favorite

4
 

In Android NDK, I build JNI files generated automatically by SWIG. callmanager_wrap.cpp is part of a shared library:

LOCAL_SRC_FILES += callmanager_wrap.cpp
include $(BUILD_SHARED_LIBRARY)

But I would like to append/edit callmanager_wrap.cpp before compiling. To be more explicit:

cat jnistuff.txt >> callmanager_wrap.cpp

Content I need to add is known in advance but callmanager_wrap.cpp is not. It is generated by SWIG. Ultimately, my custom rule will have to run following command to generate callmanager_wrap.cpp:

swig -c++ -java -package com.package.my -o callmanager_wrap.cpp callmanager.i

According to this post, it is not possible to add custom rules to Android.mk. But in Android sources, I believe there are some Android.mk handling steps after BUILT or INSTALLED. I tried the following:

MY_JNI_WRAP=callmanager_wrap.cpp

include $(CLEAR_VARS)

LOCAL_SRC_FILES += callmanager_wrap.cpp

LOCAL_INTERMEDIATE_TARGETS += myjni
myjni:
    echo "in myjni target"
    swig -c++ -java -package com.package.my -o $(MY_JNI_WRAP) callmanager.i
    cat jnistuff.txt >> $(MY_JNI_WRAP)

include $(BUILD_SHARED_LIBRARY)

But myjni target is never called.

  1. What is LOCAL_INTERMEDIATE_TARGETS used for?
  2. Can I possibly achieve what I want to do here without writing an external script or makefile?
shareimprove this question
 
    
can you clarify this sentence "I would like to append callmanager_wrap.cpp before compiling"? I can help you if you clear that up a bit. – Infinity Sep 11 '12 at 14:54
    
Do you really need to run swig on every single build? – Seva Alekseyev Sep 11 '12 at 19:37
    
On one hand, it is cleaner and prevent from versioning generated files. On the other hand, not versioning these files can break the build if developer does not make clean after a git rebase. But that's a developer's problem. Isn't it possible to custom android makefiles to that extent? I won't hide that I am considering writing a top-script to do just that but I remain curious about this android limitation. – m-ric Sep 11 '12 at 20:40
up vote 8 down vote accepted

I would suggest the following:

include $(CLEAR_VARS)

LOCAL_SRC_FILES += callmanager_wrap.cpp
MY_JNI_WRAP := $(LOCAL_PATH)/callmanager_wrap.cpp

$(MY_JNI_WRAP):
    echo "in myjni target"
    swig -c++ -java -package com.package.my -o $(MY_JNI_WRAP) callmanager.i
    cat jnistuff.txt >> $(MY_JNI_WRAP)
.PHONY: $(MY_JNI_WRAP)

include $(BUILD_SHARED_LIBRARY)

That's it.

I probably owe you some explanations. So here we go:

  1. $(LOCAL_SRC_FILES) is a list of file names relative to $(LOCAL_PATH), so to address a file from outside the standard NDK actions, you need the full path for your file, which is $(LOCAL_PATH)/callmanager_wrap.cpp.

  2. We specify the file as .PHONY to guarantee that the custom action is executed every time you run ndk-build. But if you know which are actual dependencies of callmanager_wrap.cpp, you can specify them instead, like

    $(MY_JNI_WRAP): callmanager.i jnistuff.txt $(LOCAL_PATH)/../src/com/package/my/Something.java

    In this case, you will not need the .PHONY line.

  3. If you want your source directory to remain clean, you can declare the wrapper file as .INTERMEDIATE like this:

    .INTERMEDIATE: $(MY_JNI_WRAP)

Now make will delete the wrapper file after build, if it did not exist before the build.

shareimprove this answer
 
    
I've tried your proposal with something like: MY_JNI_WRAP:=bus/callmanager_wrap.cpp LOCAL_SRC_FILES += $(MY_JNI_WRAP) $(MY_JNI_WRAP): echo "in myjni target" touch mememe .PHONY: $(MY_JNI_WRAP) But after I ran rm -rf obj/local/ libs/armeabi && ndk-build -j5, find -name mememe never returns something. Are you sure .PHONY is recognized by ndk-build? – m-ric Sep 12 '12 at 14:52
1  
In my example above, the phony target was not the same string as what I added to LOCAL_SRC_FILES. The trick is that LOCAL_SRC_FILES is relative tothe Android.mk but the make itself and its targets are relative to the current dir. tl;nr use $(LOCAL_PATH)/$(MY_JNI_WRAP) everywhere except the LOCAL_SRC_FILES line. – Alex Cohn Sep 12 '12 at 17:28
    
Wow, you made my day Alex! Thanks heaps – m-ric Sep 12 '12 at 18:15
    
Using all: $(MY_JNI_WRAP) instead of .PHONY: $(MY_JNI_WRAP) worked for me. – Juozas Kontvainis Jul 26 '13 at 13:24
    
@juozas-kontvainis: you mean, .PHONEY didn't work? – Alex Cohn Jul 26 '13 at 18:48

I have done it this way: let's say I need to create .s file from .ll file

# custom build
source_ll_files := $(wildcard *.ll)
%.s:
    llc -o $@ $(patsubst %.s,%.ll,$@)

LOCAL_SRC_FILES += $(patsubst %.ll,%.s,$(source_ll_files))
# end
shareimprove this answer

posted on 2016-11-15 13:44  Shawn X.Y. Bai  阅读(687)  评论(0编辑  收藏  举报

导航