In android mk files it is possible to call a shell command right after generating assembly files with LOCAL_FILTER_ASM.
I was wondering is there any workaround to have something similar in cmake?
I admit I had lookup what LOCAL_FILTER_ASM does.
So the following is my piece of code (same functionality just in CMake):
cmake_minimum_required(VERSION 3.0)
project(LocalFilterASM C ASM)
set(LOCAL_FILTER_ASM "cp")
string(
REPLACE
"<ASSEMBLY_SOURCE>" "<OBJECT>.S.original"
MY_CREATE_ASSEMBLY "${CMAKE_C_CREATE_ASSEMBLY_SOURCE}"
)
string(
REPLACE
"<SOURCE>" "<OBJECT>.S"
MY_COMPILE_OBJECT "${CMAKE_ASM_COMPILE_OBJECT}"
)
set(
CMAKE_C_COMPILE_OBJECT
"${MY_CREATE_ASSEMBLY}"
"${LOCAL_FILTER_ASM} <OBJECT>.S.original <OBJECT>.S"
"${MY_COMPILE_OBJECT}"
)
file(WRITE main.c "int main(void) { return 0; }")
add_executable(${PROJECT_NAME} main.c)
This just takes some of the existing CMake compiler rules and combines it into a new multi-line rule for CMAKE_C_COMPILE_OBJECT. Please note that this will only work with CMake's makefile generators.
It's very hard to say since you haven't provided any example of what you currently have.
However, you can use the add_custom_command() function to add before and after scripts to any target (see the bottom of the page in the "Build Events" section for the syntax you want).
Related
I am trying to build an executable for Android with cross compiling, everything works but the executable complains that it could not find the .so file it needs, which is in the same directory as the executable.
So what I did is to add the following lines
set(TARGET myapp)
# following 4 lines added to add RPATH of ./ to the binary
# so it searches the .so in the same directory
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_SKIP_RPATH FALSE)
set(CMAKE_INSTALL_RPATH $ORIGIN)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
# add source code to target
add_executable(${TARGET} src.cpp)
...
However, it builds the executable, but RPATH seems not working no matter how I play with the four lines above, I just could not find any RPATH info in the binary using readelf or objdump.
I also tried set_target_properties(${TARGET} PROPERTIES INSTALL_RPATH $ORIGIN) but still not working.
Did I miss use anything here for RPATH configuration?
update
just to note that if I build the app for host(Linux) (using the same cmake file except using the android ndk tool chain) then everything is fine, I see $ORIGIN in the binary RPATH using readelf.
although i dont know what is been done in android ndk tool chain
This is probably not what you want:
(I am mentioning it just to be complete with my answer)
I assume that $ORIGIN is an environment variable. If that is the case you need to explain to CMake that it is such an variable. You can use $ENV{VAR} to do this, e.g.:
set(CMAKE_INSTALL_RPATH $ENV{ORIGIN})
This is probably what you want:
Ofcourse if the variable is not accessible during CMake generation step. You can try to use bracket arguments, however I do not think that alone would work (see last note at the bottom). Bracket arguments [=[...]=] tell CMake to skip the evaluation, because $ is a special character. e.g.:
set(CMAKE_INSTALL_RPATH [=[$ORIGIN]=])
To understand what [=[]=] do here is a simple example:
set(FOO "bar")
message(STATUS ${FOO})
message(STATUS [=[${FOO}]=])
Should output
bar
${FOO} #<-- evaluation of ${FOO} was skipped
Also if I'm not mistaken you also need to pass $ORIGIN to linker with single quotes so that it doesn't get evaluated during linking, i.e.
'$ORIGIN'
#and not $ORIGIN
I'm trying to build libavformat with this MAKEFILE. Although the makefile includes avio.o file in its build instruction but it doesn't add any symbol for the functions that are declared on the header file url.h. Source folder which includes the avio.c, avio.h and url.h files can be found HERE.
The nm command for avio.o returns
nm: avio.o: File format not recognized
file command on avio.o shows the following output
avio.o: LLVM IR bitcode
I have checked the nm command on the generated libavformat.so and did not find any symbols for the functions declared on the url.h file
I have been stuck on this for two days. Could not figure out how to solve this problem!
Calling the ff_check_interrupt method and results in
undefined reference to 'ff_check_interrupt'
Configurations and flags.
FFmpeg Configuration File: Config.h
FFmpeg Root MakeFile: Root MakeFile
CC, CXX, CFLAGS, LDFLAGS: FLAGS
First off, a function declared by url.h should be defined in url.c, not in avio.c.
Second the only use of the ff_check_interrupt in avoi.c is within a static inline function, so indeed the toolchain is likely optimizing this symbol away.
I think what's occurring for you is that the toolchain making the decision that this is only used in this compilation unit.
Moving the definition of ff_check_interrupt to 'url.c' should resolve the issue. This is a library though, so out of your control.
However, this doesn't answer why thousands of users on Github have this same library in their code. I'd suggest comparing your Makefile against those (e.g. first search return is this one.
I'm trying to compile a kernel but can't figure out how its Makefile work : https://github.com/LineageOS/android_kernel_sony_msm8994/blob/cm-14.1/scripts/Makefile.build
As I have this error when building : Build of a custom Linux/Android/LineageOS kernel in C doesn't work , I'm for now trying to understand up until the line 44.
Why are there several Makefile with extensions like .build .clean etc rather than these actions being "targets" within the main Makefile?
How can I figure out what the very first $(obj) var refers to ?
Is the mathematical syntax := "equals by definition" instead of = specific to the developper? I do saw this on mathematics notes or symbolic languages such as Wolfram/Mathematica if I'm right, but never within a program.
Why does PHONY := is a variable and not a "type of action" as in the doc ? It should be written .PHONY: as on the very last line of the file. I didn't get this trick.
Why are there 2 underscores before __build the value of PHONY ?
By thanking you for your precisions
Because the person who wrote the makefile wanted to break those out into separate files. Maybe they're included in multiple other files, or they just wanted the top-level makefile to be more clean to read.
You can run make with the -p option and it will print all the values of all the variables in the makefile.
I don't quite understand the question: the := operator in a makefile is used for simply-expanded variable assignments. See the GNU make manual for more info.
That sets the variable PHONY to contain some contents. It is just a normal variable assignment, there's nothing fancy here. Presumably somewhere else in the makefile will appear a line: .PHONY: $(PHONY) and that will make all the targets in the PHONY variable phony.
Because the person who wrote the makefile wanted to use two underscores.
I am trying to add a strip debug symbols step for my Android library which includes native shared libraries for different ABIs, e.g. x86/native-lib.so, x86_64/native-lib.so, arm64-v8a/native-lib.so, etc.
I understand that the strip command must be respective to each ABI. So, I need to invoke the correct strip command, for which I need to know its correct path during build time.
For example, for ABI x86_64, I need to have below path setting:
set(STRIP ~/Library/Android/android-ndk-r16b/toolchains/x86_64-4.9/prebuilt/darwin-x86_64/bin/x86_64-linux-android-strip)
add_custom_command(TARGET ${SHARED_LIBRARY_NAME} POST_BUILD
COMMAND ${STRIP}
"${DIST_LIBS_DIR}/${LIB_BUILD_TYPE}/${ANDROID_ABI}/lib${SHARED_LIBRARY_NAME}.so"
COMMENT "Strip debug symbols done on final binary.")
The path I need is illustrated like below:
So, my questions are:
Is there an existing CMake variable to point at this path, i.e. /android-ndk-r16b/toolchains/???/prebuilt/???/bin/???-???-???-strip?
If not, is there a way to form this path utilising other known Android CMake variable, e.g. ANDROID_NDK, ANDROID_ABI, etc?
Thanks #Alex Cohn a lot for pointing out the file android.toolchain.cmake which usually exists at directory ~/Library/Android/sdk/cmake/cmake_version_xxx/android.toolchain.cmake on macOS.
There are many useful Android CMake variables already configured inside, e.g.
ANDROID_NDK
ANDROID_TOOLCHAIN
ANDROID_ABI
ANDROID_PLATFORM
ANDROID_STL
ANDROID_PIE
ANDROID_CPP_FEATURES
ANDROID_ALLOW_UNDEFINED_SYMBOLS
ANDROID_ARM_MODE
ANDROID_ARM_NEON
ANDROID_DISABLE_NO_EXECUTE
ANDROID_DISABLE_RELRO
ANDROID_DISABLE_FORMAT_STRING_CHECKS
ANDROID_CCACHE
And the one ANDROID_TOOLCHAIN_PREFIX is exactly what I looked for, so my final CMake script comes into below:
add_custom_command(TARGET ${SHARED_LIBRARY_NAME} POST_BUILD
COMMAND "${ANDROID_TOOLCHAIN_PREFIX}strip" -g -S -d --strip-debug --verbose
"${DIST_LIBS_DIR}/${LIB_BUILD_TYPE}/${ANDROID_ABI}/lib${SHARED_LIBRARY_NAME}.so"
COMMENT "Strip debug symbols done on final binary.")
And I don't need to explicitly pass any additional arguments, i.e. DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake, from command line to the build process. Because, this file, i.e. android.toolchain.cmake, was already taken into account automatically by Android native build system.
You can use ${CMAKE_STRIP}. It is set appropriately when you use -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake. I hope it is OK also if you work with 'built-in' Android support with supported NDK version.
I use Android NDK r8 to generate multiple static libraries with include $(BUILD_STATIC_LIBRARY) and I successfully get : lib1.a, lib2.a, lib3.a, etc.
Now I would like to merge these static libraries into single one.
I try do it with ar.exe from Android NDK :
android-ndk-r8\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\arm-linux-androideabi\bin\ar.exe r libALL.a lib1.a lib2.a lib3.a
But when I use libAll.a into Android NDK makefile, it fails saying there is no index.
How can I add this index ?
Other question :
When I display contents of archive libAll.a, I see lib1.a, lib2.a, lib3.a instead of .o symbols from these libraries.
How can I change that (= extract .o from static libraries to merge it in libAll.a) ?
Thanks
ar is simply an archiving tool like zip. It takes the given input files and produces an .aarchive. If you want to include all .ofiles in a single archive, you have to specify each individual file. I don't know how to do this on WIndows, but on Linux you can use somthing like ar rs $(find . -name *.o).