I am trying to build FFMPEG 4.2 using Android NDK r20 and I am having an issue with configure.
I followed Ilia Kosynkin's blog post (https://medium.com/#ilja.kosynkin/building-ffmpeg-4-0-for-android-with-clang-642e4911c31e) and with a few minor changes to build.sh I successfully built FFMPEG 4.0.2 using Android NDK r17c for API level 14 on an Ubuntu 16 VM.
I updated FFMPEG to 4.2 and the Android NDK to r20 and got these and other compiler errors.
~/android-ndk/sysroot/usr/include/stdlib.h:61:7: error: expected identifier or '('
char* getenv(const char* __name);
^
./config.h:17:19: note: expanded from macro 'getenv'
#define getenv(x) NULL
^
~/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/8.0.7/include/stddef.h:105:18: note: expanded from macro 'NULL'
# define NULL ((void*)0)
and many like this:
./libavutil/libm.h:54:32: error: static declaration of 'cbrt' follows non-static declaration
static av_always_inline double cbrt(double x)
^
~/android-ndk/sysroot/usr/include/math.h:191:8: note: previous declaration is here
double cbrt(double __x);
^
In addition to cbrt there were about a dozen or so other math related functions redefined (e.g. lrint, round, trunc, inet_aton). I opened the generated config.h, commented out #define getenv(x) NULL and changed a bunch of defines like #define HAVE_CBRT 0 to #define HAVE_CBRT 1. I ran make and make install and the build was successful.
So my question is, are there ffmpeg options that I can pass to configure that will generate a config.h that I don't have to modify in order to get a successful build?
EDIT: Additional information from config.log.
It appears that check_mathfunc in configure is failing for NDK r20 but I can't tell why. Here is an example of a link command failing for the check for truncf. The error does not make any sense to me.
~/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ld
-L~/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x
-L~/android-ndk/platforms/android-29/arch-arm/usr/lib
--fix-cortex-a8 -lc --sysroot=~/android-ndk/sysroot -fPIE -pie
-o /tmp/ffconf.1OTX8pa8/test /tmp/ffconf.1OTX8pa8/test.o -lgcc
~/android-ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ld:
fatal error: -f/--auxiliary may not be used without -shared
EDIT 2: The error seems to be caused by the -pie option (Create a position independent executable). Previous version of FFMPEG did not have these 2 lines in the configure script for android:
add_cflags -fPIE
add_ldexeflags -fPIE, -pie
If I add -shared to add_ldexeflags I get the error "-shared and -pie are incompatible". If I replace -pie with -shared, check_mathfunc succeeds but I don't know if that is the correct thing to do. It seems odd that -fPIE requires -shared but -pie cannot be used with it.
Replacing -pie with -shared seems to fix the config.h file but now I get 'sys/sysctl.h' file not found during the build of libavutil. NDK r20 has 2 instances of sysctl.h and NDK r17c has 1 but none of them are in a directory named sys.
EDIT 3: I am going to chalk this one up to a bug in the FFMPEG configure script. configure checks for the existence of a function by generating a small source file that uses the function and then compiling and linking the generated file. If anything fails the function is not available. For NDK r17c, check_func sysctl fails and the build excludes sysctl functionality. For some reason, the test succeeds for NDK r20 because check_func does not verify whether or not sys/sysctl.h exists it just prototypes sysctl() and calls it. I solved this issue by adding a function to configure named check_sysfunc that tries to include sys/sysctl.h. I now get past this error and have a new one about an implicit declaration being invalid. I have to assume it is also a deficiency in configure and hopefully there won't be too many more of these.
I'm currently trying to do the same thing as you. Apparently, this guy (not me) manage to compile ffmpeg4.2 with NDK r20. So far it seem to work with ARCH=armv7a
[Youtube] https://www.youtube.com/watch?v=RP8SEAhcq5M
[Github] https://github.com/binglingziyu/ffmpeg-android-build
[P.s. I don't have enough reputation to post as a comment... so yeah...]
Passing -fPIE to ld directly is wrong. That's a compiler flag. The linker flag is spelled -pie. -fPIE is -f PIE, which is a completely different argument:
https://linux.die.net/man/1/ld
-f name
--auxiliary=name When creating an ELF shared object, set the internal DT_AUXILIARY field to the specified name. This tells the dynamic
linker that the symbol table of the shared object should be used as an
auxiliary filter on the symbol table of the shared object name. If you
later link a program against this filter object, then, when you run
the program, the dynamic linker will see the DT_AUXILIARY field. If
the dynamic linker resolves any symbols from the filter object, it
will first check whether there is a definition in the shared object
name. If there is one, it will be used instead of the definition in
the filter object. The shared object name need not exist. Thus the
shared object name may be used to provide an alternative
implementation of certain functions, perhaps for debugging or for
machine specific performance.
This option may be specified more than once. The DT_AUXILIARY entries
will be created in the order in which they appear on the command line.
As for the other issue:
NDK r20 has 2 instances of sysctl.h and NDK r17c has 1 but none of them are in a directory named sys.
I just filed https://github.com/android-ndk/ndk/issues/1068, but I'm not sure if we'll fix that one. Apparently its use is strongly discouraged. Fixing the source to not use that is probably the better call.
I picked up the following demo off the web from https://computing.llnl.gov/tutorials/pthreads/
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
But when I compile it on my machine (running Ubuntu Linux 9.04) I get the following error:
corey#ubuntu:~/demo$ gcc -o term term.c
term.c: In function ‘main’:
term.c:23: warning: incompatible implicit declaration of built-in function ‘exit’
/tmp/cc8BMzwx.o: In function `main':
term.c:(.text+0x82): undefined reference to `pthread_create'
collect2: ld returned 1 exit status
This doesn't make any sense to me, because the header includes pthread.h, which should have the pthread_create function. Any ideas what's going wrong?
For Linux the correct command is:
gcc -pthread -o term term.c
In general, libraries should follow sources and objects on command line, and -lpthread is not an "option", it's a library specification. On a system with only libpthread.a installed,
gcc -lpthread ...
will fail to link.
Read this or this detailed explanation.
For Linux the correct command is:
gcc -o term term.c -lpthread
you have to put -lpthread just after the compile command,this command will tell to the compiler to execute program with pthread.h library.
gcc -l links with a library file.Link -l with library name without the lib prefix.
in eclipse
properties->c/c++Build->setting->GCC C++ linker->libraries in top part add "pthread"
Running from the Linux terminal, what worked for me was compiling using the following command (suppose the c file I want to compile is called test.c):
gcc -o test test.c -pthread
Hope it helps somebody!
If you are using cmake, you can use:
add_compile_options(-pthread)
Or
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
I believe the proper way of adding pthread in CMake is with the following
find_package (Threads REQUIRED)
target_link_libraries(helloworld
${CMAKE_THREAD_LIBS_INIT}
)
Acutally, it gives several examples of compile commands used for pthreads codes are listed in the table below, if you continue reading the following tutorial:
https://computing.llnl.gov/tutorials/pthreads/#Compiling
Compile it like this : gcc demo.c -o demo -pthread
In Visual Studio 2019 specify -pthread in the property pages for the project under:
Linker -> Command Line -> Additional Options
Type in -pthread in the textbox.
You need to use the option -lpthread with gcc.
you need only Add "pthread" in proprieties=>C/C++ build=>GCC C++ Linker=>Libraries=> top part "Libraries(-l)".
thats it
check man page and you will get.
Compile and link with -pthread.
SYNOPSIS
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compile and link with -pthread.
....
Since none of the answers exactly covered my need (using MSVS Code), I add here my experience with this IDE and CMAKE build tools too.
Step 1: Make sure in your .cpp, (or .hpp if needed) you have included:
#include <functional>
Step 2 For MSVSCode IDE users:
Add this line to your c_cpp_properties.json file:
"compilerArgs": ["-pthread"],
Step 2 For CMAKE build tools users:
Add this line to your CMakeLists.txt
set(CMAKE_CXX_FLAGS "-pthread")
Note: Adding flag -lpthread (instead of -pthread) results in failed linking.
From man gcc,
-pthread
Define additional macros required for using the POSIX threads library.
You should use this option consistently for both compilation and linking.
This option is supported on GNU/Linux targets,
most other Unix derivatives,
and also on x86 Cygwin and MinGW targets.
It is correct that -pthread is an option and the best way to handle this.
There are statements in some answers that it generates different compiled code. This is misleading.
If you wish to duplicate -pthread, you could use -lpthread -D_REENTRANT=1. So there are two things going on with the -pthread option.
Indeed it links with the pthread library as many answers express. Also, the order of the pthread library is important because it may override some weak symbols. So a correct version using -lpthread may need to have it multiple times on the command line.
The other important part is the _REENTRANT define. Note, that this is in the implementation namespace. Some people may care for portability and other not. However, it is very important that it is defined as the first thing in the compilation unit. This symbol will alter the way that many system headers files are parsed.
You can include #define _REENTRANT 1 at the top of every source file, but it is much easier to have it on the command line. Again, the -pthread is the best way to achieve this. Also, gcc may change the way this is implemented in the future. However, I think it is important for programmers to understand what is going on.
term.c: In function ‘main’: term.c:23: warning: incompatible implicit
declaration of built-in function ‘exit’
You never included <stdlib.h>, where exit() is declared. Also, I think newer versions of gcc have removed the need for _REENTRANT.
Why features.h?
Example on godbolt, without -pthread.
So, it is NOT generating different code. Ie, the backend of the compiler is NOT different. It is only conditional compilation and linking to different libraries. It does not generate 'lock free' code or add appropriate machine barriers because you have used this option.
In Anjuta, go to the Build menu, then Configure Project.
In the Configure Options box, add:
LDFLAGS='-lpthread'
Hope it'll help somebody too...
Sometimes, if you use multiple library, check the library dependency.
(e.g. -lpthread -lSDL... <==> ... -lSDL -lpthread)
With GCC, when the -Wall -Wextra flags are enabled, one has the option of disabling warnings such as the following with -Wno-ignored-qualifiers:
warning: 'const' type qualifier on return type has no effect
Is there any way to achieve the same behavior with LLVM/Clang? I Googled it, but only found some patch related pages about how this error reporting feature got added. Nothing on how to disable it.
I am using LLVM & Clang version 3.0 (build from SVN sources).
Note: I was going to post this on SuperUser, but there's not a single question about Clang there and no LLVM tag either, so that kind of discouraged me. If this question should be there anyway, feel free to move it.
[Edit] It seems the option is recognized when I run my Makefile from the terminal. When ran from Eclipse (Helios), it doesn't get recognized however.
[Solution] Found it. Apparently, the problem was Eclipse (under Ubuntu) is started by root. Why this is, I have no idea, but the effect is that the $PATH variable contains what root would have, instead what the user starting Eclipse would have. As such, Eclipse was using an older system-wide installed version of Clang (2.80). Adding the correct PATH variable in Project Properties -> C/C++ Build -> Environment fixed this.
What version of Clang are you using? -Wno-ignored-qualifiers works for me:
% clang -Wall -Wextra -c foo.c
foo.c:1:1: warning: 'const' type qualifier on return type has no effect
[-Wignored-qualifiers]
const int foo();
^~~~~
1 warning generated.
% clang -Wall -Wextra -Wno-ignored-qualifiers -c foo.c
%
In general you can look at the .td files, which do a pretty nice job of collecting all the diagnostics. (There's a TODO in the Clang docs to autogenerate documentation with tblgen, but this hasn't been done yet.)
In this case for example you see in DiagnosticSemaKinds.td:
def warn_qual_return_type : Warning<
"'%0' type qualifier%s1 on return type %plural{1:has|:have}1 no effect">,
InGroup<IgnoredQualifiers>, DefaultIgnore;
which shows you what diagnostic group it's in (IgnoredQualifiers). Then you can look in DiagnosticGroups.td to see what IgnoredQualifiers is called on the command line:
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
So -Wno-ignored-qualifiers is it. Clang tries to be GCC-compatible wherever possible, so using the GCC name for something is usually likely to work.
I am trying to build a certain library under cygwin (OpenEXR), and I get the following error:
b44ExpLogTable.cpp:52:18: error: half.h: No such file or directory
half.h is referenced using #include <half.h>, and is actually a part of another library I successfully run make/make install on previously.
The question is -- when using #include with <>, where the preprocessor expects to find the specified file?
(I have just found it in /usr/local/include/OpenEXR, but I have no idea why preprocessor cannot).
Update: I have also found:
Makefile
ILMBASE_CXXFLAGS = -I/usr/local/include/OpenEXR
Makefile.am
INCLUDES = #ILMBASE_CXXFLAGS# \
-I$(top_builddir) \
-I$(top_srcdir)/config
This actually decreased my understanding of what the problem may be.
Update 2: So, by redefining some variables in makefile I found out that instead of $(CXXCOMPILE) make seems to run $(CXX) $(CXXFLAGS), with CXXFLAGS being just -g -O2. Ok, I have no idea how it manages to run $(CXX) $(CXXFLAGS) if this combination in not used anywhere in the makefile except in $(CXXCOMPILE) which is not run. I can add my -I to CXXFLAGS but I have a feeling that a lot more additions will be required, so I would prefer to find a root cause of the problem.
(I am not sure whether it is a Super User or Stack Overflow question, because my developer skills in C++/Linux are almost non-existent.)
Additional include directories are usually specified in CPPFLAGS. Try running ./configure CPPFLAGS=-I/usr/local/include/OpenEXR and re-running make.
You need to somehow get -I/usr/local/include/OpenEXR added to the compiler command line. That might be a simple matter of doing:
CFLAGS=-I/usr/local/include/OpenEXR make
I am trying to compile Ruby on HPUX but get the following:
cc: "transcode.c", line 1489: error 1588: "SIZE_MAX" undefined.
cc: "transcode.c", line 1489: error 1563: Expression in if must be scalar.
I had a problem with SIZE_MAX being undefined using aCC compiler without the C99 flag. Using this environment option in the ./configure got me past it, but I'm hitting other problems later on (miniruby compiles and links, but throws a Bus Error when the make process continues :-/). Does this help you build?
CC="cc -AC99" CPPFLAGS="-D_HPUX_SOURCE" ./configure
What HPUX and compiler version?
If I remember correctly SIZE_MAX is only available if you use c99 compiler and include stdint.h (not limits.h).