I have a variable definition in an Android JNI C function that does nothing but define itself as a string. I want this string to appear in the binary, but when I build the project, the .so file does not contain the string.
Here's what I've tried in the C code.
#pragma GCC push_options
#pragma GCC optimize ("O0")
const char volatile myString[32] = "Some string that must be there";
#pragma GCC pop_options
How can I get disable the compiler from optimizing away this unused variable definition?
I suspect that your problem is not with the compilation, but with the linking. Linkers often leave out data that is not used, to reduce the size of the binary. To check this, use the strings command or equivalent on the .o file generated from your C file: if the string is in that, but not in your .so your problem is the linking.
Unfortunately, I don't know how to work around this problem with the linker command(s), because all of my Android C programming has been done with a standalone tool-chain and a custom build system.
Your easiest solution is simply to make a copy of the string at run-time. You need to do this in your C code, so that the linker knows the string gets used.
Related
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.
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).
How are the names that appear for a symbol generated in a shared library file? For example, when using elfread -Ws to read the symbols in the libutils.so file (android system utils library), I get several symbol names of the format:
_ZN7android10VectorImpl14insertVectorAtERKS0_j
etc. How do you decipher this symbol name?
That appears to be a mangled name, e.g., for C++, and you can make better sense of those using the -C option of nm:
-C
--demangle[=style]
Decode (demangle) low-level symbol names into user-level names. Besides removing any initial underscore prepended by the system, this makes C++ function names readable. Different compilers have different mangling styles. The optional demangling style argument can be used to choose an appropriate demangling style for your compiler. See c++filt, for more information on demangling.
When using nm on shared libraries, this option shows their symbols:
-D
--dynamic
Display the dynamic symbols rather than the normal symbols. This is only meaningful for dynamic objects, such as certain types of shared libraries.
Even a simple code like this gives the error
string test= "hello";
string part = test.substr(2, 3);
Invalid arguments Candidates are: stlpmtx_std::basic_string,stlpmtx_std::allocator> substr(?, ?)
Even casting to size_t did not not help
string part = test.substr((size_t)2, (size_t)3);
But both pieces of code working when running it as a console application using gcc 4.6 on Linux.
But when using Androind NDK it gives me the error.
If I close the file in the editor and close Eclipse, and then open Eclipse and build the project it compiles. But if I have the file open it throws up the error.
I am using APP_STL:= stlport_static in the Application.mk make file
Yes I did include <string>
Edit: I just looked at the times of .so file, it seems to be compiling even though Eclipse is showing the errors.
I found the solution I need to have to have stlport system include folder in the Paths and Symbols section of project properties -> C/C++ General
path_To_NDK/sources/cxx-stl/system/include
I only had the
path_To_NDK/sources/cxx-stl/stlport/stlport