Emscripten: Linking library to project - ffmpeg

I'm trying to build a small project that uses ffmpeg library to WebAssembly, with use of Emscripten. Before that, I tried it out by transpiling some simple program from C into Wasm and it worked fine, but that time I was not using any additional libraries.
For C++ I'm working with Visual Studio and FFmpeg I linked in project's "Properties" as follows:
all .h header files I placed in "include" catalog and I added it as "Additional Include Directories" in "C/C++" section
all .lib and .dll.a (for example avcodec.lib or libavcodec.dll.a) files I placed in "lib" and added as "Additional Library Directories" in "Linker" section
All includes and the program itself works fine, so now I was trying to prepare a Wasm module with Emscripten with the same same command that I used earlier, but already knowing that is not going to work:
em++ cut_video.cpp -Os -g1 -L lib -I include -s WASM=1 -s FORCE_FILESYSTEM=1 -s ALLOW_MEMORY_GROWTH=1 -s EXPORT_ES6=1 -s MODULARIZE=1 -s "EXPORT_NAME='Editor'" -s "ENVIRONMENT='web'" -s EXPORTED_FUNCTIONS="['_doubler', '_cut_video', '_cut_video1']" -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s ASSERTIONS=1 --bind -o cutter.js
I added the "-I include" parameter which is suppose to be pointing to the same header files, that I mentioned above, and it seems to be fine for Emscripten, because the initial error was solved by it.
Emscripten already found out the problem with functions from ffmpeg library, so I added "ERROR_ON_UNDEFINED_SYMBOLS=0" just to see what will happen when I will add this module to front-end app. Obviously it end up with error "missing function: av_register_all", which is first ffmpeg function within my code.
All explanations that can be helpful I found really unclear for me, because generally I'm not working with C++ or Linux environment, so I'm not fimilliar with Makefile or so.
Is there a way, basing on what I described and how my project was prepared with Visual Studio, to tell the Emscripten to use those pre-build .dll.a or .lib files of FFmpeg for my app? Or how should I modify my project to make it acceptable for Emscripten?
Edit: Since cut_video.cpp file is quite big, maybe it's a better idea to just paste here a link to this file on github instead of the big block of code.

FFmpeg and Emscripten
Build the FFmpeg libs with Emscripten is not an easy task, but you can follow the ffmpeg.wasm tutorials:
Introduction
Build with Emscripten
Read carefully until the end all the tutorial, because there are so many issues that can arise.
Note
I suggest to you to start with the FFmpeg and Emscripten version used in the tutorial and look at the build-ffmpeg.sh script. The script itself export a wasm file with a main function
https://github.com/ffmpegwasm/ffmpeg.wasm-core/blob/85f0e51d9a94447a3b3481c7a4794c2eb9abbfee/wasm/build-scripts/build-ffmpeg.sh#L22
-s EXPORTED_FUNCTIONS="[_main, _proxy_main]" # export main and proxy_main funcs
that is, the main function from fftools/ffmpeg.c. This will help you a lot.
Useful resources
Note that in the Emscripten docs there is a list of C/C++ libraries/project ported to WASM/Javascript, there are some FFmpeg projects see utilities
Happy coding!

the option returns linking error :
emcc: error: undefined exported symbol: "_proxy_main" [-Wundefined] [-Werror]
does the USE_PTHREAD option generate the proxy_main(...) function to abstract the main(...) ?
-s USE_PTHREADS=1 # enable pthreads support
-s PROXY_TO_PTHREAD=1 # detach main() from browser/UI main thread
-s INVOKE_RUN=0 # not to run the main() in the beginning
-s EXIT_RUNTIME=1 # exit runtime after execution
-s EXPORTED_FUNCTIONS="[_main, _proxy_main]" # export main and proxy_main funcs

Related

Cannot link against cmake imported targets

I am trying to compile a project with a large code base and (possibly) not fully up-to-date CMakeLists.txt. The software has several components. In particular you separately build core of the application and then proceed to build various extensions. The core also uses boost as one of its many dependencies.
I successfully configured and built the core component. I am now building the GUI extension. Configure is successful but make fails whilst linking against boost with the following errors:
/usr/bin/ld: cannot find -lBoost::filesystem
/usr/bin/ld: cannot find -lBoost::system
I can fix this by manually invoking gcc with -lBoost::filesystem replaced by-lboost_filesystem.
Clearly something went wrong with the configuration. When I inspect the variables with ccmake I can confirm that cmake is pointing to the right boost directory. After investigating CMakeLists.txt I found that ${Boost_FILESYSTEM_LIBRARY} is referenced in the core source code, but not in extension e.g.
SET(COMMON_LIBS
Registry
...
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
)
...
TARGET_LINK_LIBRARIES(Launcher ResourcesManager ${LIBBATCH_LIBRARIES} ${LIBXML2_LIBS} ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY})
...
TARGET_LINK_LIBRARIES(SalomeLauncher Launcher ${COMMON_LIBS})
Could you please point me in the right direction? In particular do problem like this indicate issues with Boost, with the application kernel or with application extension? Any hint at this stage would be useful.
Motivation and setup
I am trying to compile SALOME on Arch Linux with cmake version 3.17.1.
I am going to post a less manual solution in case anyone comes across it and cannot fix their CMakeLists.txt. I ended up using sed to automate this build:
cmake \
-DCMAKE_BUILD_TYPE=Release \
...
../ \
&& find -name link.txt -exec sed -i \
-e 's/Boost::filesystem/boost_filesystem/' \
-e 's/Boost::system/boost_system/' {} \; \
&& make -j && make install
This should obviously not be necessary, but if cannot debug your build systems, it should work.

Link ffmpeg lib statically in Visual Studio

I'm trying to use ffmpeg in my C++ project on VS2010, and the ffmpeg dev version provides the lib of .h files. I linked these .libs in my projects and the corresponding .dlls are required when running the .exe file. But I want to link the ffmpeg lib statically and running without .dlls.
I tryed to compile the ffmpeg source code on windows with Mingw, only resulting on some .a archive files. How to get ffmpeg static .lib files? And it's a 64bit program so 64bit static lib is required.
In your output directory, you have some *.def files. You can use these files to get your *.lib files. The syntax is:
lib /def:avcodec-54.def /out:avcodec-54.lib
Use the lib.exe of your VS version. Mine is located in C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin. Check the command line options (it way be useful to add /machine:i386).
Another way to do this: instead of using windows's cmd directly to start msys/mingw, first start VS command prompt (you can start it from Start menu). It will set some environment variables. From here, compile FFmpeg with msys/mingw: FFmpeg build will autodetect that VS is present, thus will auto-perform the libcall.
Edit: Sorry, I skipped the "static" part of the question. Here are some tips for a static build (note that I've never build a static FFmpeg used inside visual studio, so maybe it will not work).
First, of course, FFmpeg must be built with the static options: just to be sure, I use these options, so I have no .def of shared files:
./configure --enable-static --disable-shared [other options]
In order to have statically files, you may directly use the .a files (again: I never thried this). Check this question.
If it does not work, you can try the visual studio toochain instead of gcc. But be careful: last time I tried this (but a shared dll), FFmpeg decoding was slower when build from msvc than gcc's output. Check this page for detailed build instructions.

XML Parser in OCaml for Windows

I have found several libraries for XML Parser in OCaml, such as PXP or XML-Light. Anyone knows such a thing that can be used easily in Windows? I found that in XML-Light, they have several .ml and .mli files, I try to copy it to the lib folder of my ocaml, but it doesn't work. Any advice how to do this correctly?
Thank you a bunch.
NB: I don't use cygwin either. I use a MSVC version of OCaml.
I've used xmlm for xml parsing. For simplest installation scenario you can download its distribution and copy src\xmlm.ml into your project directory.
Alternatively, you may compile it using:
ocamlopt -c xmlm.mli
ocamlopt -c xmlm.ml
and put the resulting files into %OCAMLLIB%\xmlm directory. Then you can compile your project like this:
ocamlopt -I +xmlm xmlm.cmx foo.ml -o bar

How do I build a Win32 app with a resource file using cmake and MinGW?

In theory, it's very easy to build a Win32 app with a resource file using cmake. In an add_executable command, a resource file can be listed as easily as a C or C++ source file. There is a known bug, however, when building using MinGW tools.
I found a workaround, which is to include the following in CMakeFiles.txt...
if(MINGW)
set(CMAKE_RC_COMPILER_INIT windres)
ENABLE_LANGUAGE(RC)
SET(CMAKE_RC_COMPILE_OBJECT
"<CMAKE_RC_COMPILER> <FLAGS> <DEFINES> -o <OBJECT> <SOURCE>")
endif(MINGW)
Unfortunately, this doesn't seem to work. What seems to happen is that windres generates a <whatever>.rc.res file which ld doesn't understand.
In my searches, I've developed a strong suspicion that Win32 support is seen as a very low priority, especially outside of Visual Studio. This is understandable, as Win32 obviously isn't as important as it once was. And of course Visual Studio Express Editions are easily available for free.
Even so, it would be convenient for me if I could use MinGW GCC for a few old Win32 apps I still use. If nothing else, I can get GCOV test coverage stats.
Obviously if all else fails, I could always handle resource files using a custom build command. One issue is that I'm not familiar with either windres or ld, or how MinGW is meant to handle Win32 resource files. Another is that I don't really want to reinvent the wheel if someone already has a superior wheel they'd like to share with me.
So that's basically it - how can I support building Win32 apps with resource files using cmake, and using MinGW (but not breaking support for Visual Studio)?
I think, your problem is here:
<CMAKE_RC_COMPILER> <FLAGS> <DEFINES> -o <OBJECT> <SOURCE>
Maybe you should write something like this:
<CMAKE_RC_COMPILER> <SOURCE> <OBJECT>
Or more formal:
<CMAKE_RC_COMPILER> -i <SOURCE> -o <OBJECT>
The other possible problem could be with - which extension does cmake substitutes? As windress will guess the needed output file format from that.
References are here:
www.mingw.org/wiki/MS_resource_compiler
"res" files are unappropriate for ld, as you already know, and the windres example
sourceware.org/binutils/docs/binutils/windres.html
windres man
EDIT by question author...
The fixed cmake code snippet is as follows...
if(MINGW)
set(CMAKE_RC_COMPILER_INIT windres)
ENABLE_LANGUAGE(RC)
SET(CMAKE_RC_COMPILE_OBJECT
"<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
endif(MINGW)
It should probably be setting a flags variable rather than inserting the -O option in the command template, but this works.

Using Boost with Cygwin on Windows

This shoud be a simple problem for users more advanced than I am. :-)
How do I use the boost library with cygwin on windows?
I am programing with g++ using cygwin on a winxp machine.
I need modified Bessel functions of the second order, so I downloaded the latest version of the boost library and installed it in
'c:\cygwin\lib\boost_ 1_ 38_0\' folder.
I am trying to run the "example.cpp" program from the "getting started" section of their website:
http://www.boost.org/doc/libs/1_35_0/more/getting_started/unix-variants.html
I am compiling from the directory where I created the example file using a simple Bash shell command line: 'g++ -Wall example.cpp'
I keep getting the message:
"boost/lambda/lambda.hpp: no such file or directory"
I tried every possible combination of -L, -l, -I options in the command line to include the directory, to no avail. Also tried to add the folder in the PATH line of my windows system.
How do I link to the /boost directory and ALSO to all subdirectories? The header file 'lambda.hpp' is calling other header files in subdirectories.
You're probably not that familiar with C++ yet? It seems you are confusing terms.
C++ programs are built in two steps: compiling and linking. In the first step, each source file (typically called .cpp) is handled individually. Each .cpp file usually uses multiple headers, so the compiler first inserts those - literally. That's why it's called #include.
In the second step, the linker takes all the compiled .cpp files together and builds your final program. Some of those compiled .cpp's might have been bundled together before, in which the bundle is called a library.
Boost is a collection of headers and .cpp files. So, both compiler and linker might need to find the Boost directories. From your error message, it's clear that the compiler step is the problem. The linker does not need headers anymore.
The compiler will see the #include <boost/lambda/lambda.hpp> instuction. That means it needs to know where that first-level boost directory is found. I would guess at this point that the path would be /lib/boost_ 1_ 38_0/include (there's always the find / -name lambda.hpp shotgun appraoch)
If you are not utterly wedded to cygwin, you should take a look at http://nuwen.net/mingw.html which gives you a complete MinGW C++ installation with all the libraries (such as Boost) set up for you.
Edit: I should make it clear you can use this MinGW installation in addition to Cygwin, not as a replacement. Just make sure the MinGW bin directory appears in your PATH before the Cygwin one.
I think you need -I /lib/boost_1_38_0 - although that's a pretty unusual place to put it. You'll have to let us know how you installed it, did you just unzip it in the location you said, or did you run the makefiles? I assume that since you gave a windows path you didn't install it within cygwin - which you probably should do. The instructions in the getting started guide for unix should help - although don't download a prebuilt bjam - it needs to be built with cygwin.
But if you're not very familiar with cygwin (or unix in general) I think you might find it easier to use a native windows tool - as in Neil Butterworth's answer.
Thank you all for the information, it's a nice introduction to the use of libraries with cygwin.
Daniel was right. While any variation gives an error, the following line (using caps i) does the trick:
g++ -Wall -I /cygdrive/c/cygwin/lib/boost_1_38_0/ example.cpp -o example
I will also check MinGW in the next few days.
p.s. I simply downloaded and unzipped boost in that folder, but since I am only using header files I probably won't need to compile with cygwin. [The boost version included with cygwin was 1.33, which does not seem to have Bessel functions.]
This is on win7 cygwin64 g++ 5.4, and boost-1.64.7z on 2017-7. Google doesn't show any useful result for getting started for boost on windows (is boost out of fashion?).
By experimenting, I managed to compile and run a boost graph sample program as follows:
:: g++ 5.4 in c:\cygwin64
:: 7z extract boost download in c:\tools\boost\boost164
> set BOOST_ROOT=c:\tools\boost\boost164
> setx BOOST_ROOT c:\tools\boost\boost164 -m
> cd %BOOST_ROOT%
> bootstrap.sh gcc (the bat files doesn't work)
> b2.exe
...failed updating 58 targets...
...skipped 18 targets...
...updated 1123 targets...
:: Lots of example here (not ranked highly by google)
> mklink /D eg %BOOST_ROOT%/libs/graph/example
:: Compiled and run [maxflow code using boost library][1]
:: http://vision.csd.uwo.ca/code
> unzip ; vi Makefile
CPPFLAGS = -I %BOOST_ROOT%/
LDFLAGS = -L%BOOST_ROOT%/stage/lib
> make
> set PATH=%PATH%;%BOOST_ROOT%/stage/lib
> maxflow.exe
Flow = 6

Resources