Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emscripten: emmake generating .js files

According to the Emscripten Docs

Make generates linked LLVM bitcode. It does not automatically generate JavaScript during linking because all the files must be compiled using the same optimizations and compiler options — and it makes sense to do this in the final conversion from bitcode to JavaScript.

Which is great and what I want to do. However, running Emscripten to compile the openjpeg .jp2 library generates 4 uncompressed (-O0) .js files in the 5-6mb range, and three identical bytecode .so files of 514kb, which don't seem to contain the code I need. When I run them through emcc they come out as 141kb, without a _main function or anything recognizable, and don't behave the same as the other .js files.

What do I need to change to generate correct bytecode with the emmake command rather than .js files?

emcmake cmake completes ok and then emmake make works, but I don't have the option to try various optimizations or any of the options emcc would normally give.

I'm attempting this compilation on Lubuntu 15.04 in a vbox under Win 8. This is my first emscripten project other than the tutorials. I'm also not very familiar with c or c++ or compilation in general (though I can compile this project into Linux applications with no problems).

I'm aware of j2k.js, but I'm looking for obj_compress, not obj_decompress.

like image 608
Josiah Avatar asked Jul 22 '15 15:07

Josiah


Video Answer


1 Answers

I am not sure about the usage of emcmake or emmake directly but worked on a CMAKE based C++ project, a main executable, that used be compiled to an x86_64 executable on linux, and that I converted to emscriptem in order to deploy it on an Nginx server.

CMAKE cross compilation + target platform and ouput = Toolchain File + linker flags + compiler flags

openjpeg.jp2 project is a CMAKE C/C++ program.

Here you are trying to cross compile a C/C++ lib or executable from your host linux x86 with GCC for instance, could also be Windows + Visual C++ compiler.

Toolchain file

You need a CMAKE toolchain file that's gonna tell CMAKE how to use emscriptem tools including the emscriptem compiler, and linker that produce JS or WebAssembly.

  • Get an Emscriptem cmake toolchain file example here linux GCC x86: https://gist.github.com/romatou18/9f631147b5b26f980ab9669c375a6e3f

Compiler flags

  • When using a CMAKE project refer to the CMakeLists.txt file in order to find/apply/modify the compiler and linker flags based on debug/release build types selected i.e. the GCC build flag for the openjpeg.jp2 project:

example of compiler flags: https://github.com/uclouvain/openjpeg/blob/172c8ae5cf230ff74b5814daf29e5b577aa30a9b/CMakeLists.txt#L200

Again I do not know the specifics of emmake/emcmake but if your project is CMAKE based, the toolchain file should tell CMAKE all that it needs to know to compile your program.

Emscriptem Linker flags : choose Native JS or WebAssembly output

CMakelists.txt that specifies emscriptem linker flags and selects either JS or WebAssembly as an output based on the JS_ONLY option:

cmake_minimum_required(VERSION 3.6)
message( "Current dir: ${CMAKE_CURRENT_LIST_DIR}" )

#make sure it is all static
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
SET(BUILD_SHARED_LIBRARIES OFF)

option(JS_ONLY "Compiles to native JS (No WASM)" OFF)

add_executable( myProgram main.cpp)
target_link_libraries( myProgram ${API_LIB})
target_compile_features(myProgram PRIVATE cxx_std_14)


if(JS_ONLY)
  message(STATUS "Setting compilation target to native JavaScript")
  set(CMAKE_EXECUTABLE_SUFFIX ".js")
  set_target_properties(myProgram PROPERTIES LINK_FLAGS "--emrun -s EXPORTED_FUNCTIONS='[_main]'")
else(JS_ONLY)
  message(STATUS "Setting compilation target to WASM")
  set(CMAKE_EXECUTABLE_SUFFIX ".wasm.js")
  set_target_properties(myProgram PROPERTIES LINK_FLAGS "--emrun -s WASM=1 -s BINARYEN_METHOD='native-wasm' -s EXPORTED_FUNCTIONS='[_main]' -s NO_EXIT_RUNTIME=1 -s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']")
endif(JS_ONLY)

#- Compiling to emscriptem/js output: PROPERTIES LINK_FLAGS set to --emrun -s 

#- Compiling to emscriptem/WASM => webAssembly output: PROPERTIES LINK_FLAGS set to --emrun -s WASM=1 -s BINARYEN_METHOD='native-wasm'


Note WebAssembly is the lowest output level you will get with EmscriptEm, should be a more compact that JS in theory.

Customising the Cmakelist.txt

On this specific project, reuse the example CMakeLists.txt i gave above and customise it:

  • Setup your emscriptem target like mentioned above with the link flag on the emscriptem target
set_target_properties(... PROPERTIES LINK_FLAGS "--emrun -s <emscript em link flags as described above>)
  • Configure release build compiler flags for the release build C AND OR C++ depending on the source language(s) of the project, C flags example below:
set(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb -Wall -Wunused-variable -Wno-unused-parameter -fno-inline ... etc ...etc ...")
set(CMAKE_C_FLAGS_RELEASE "-O2 -Wno-format-security -Wno-format-nonliteral -Wall -Wunused-variable -Wno-unused-parameter")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} [+ optional extra flags for both here...]"

Running the cmake config

Now is the time to use the toolchain file:

  • Run cmake using the desired build type and specify the toolchain file that tells CMAKE how to use emscriptem, TAKEN from the gist above:
cmake -DCMAKE_BUILD_TYPE:string="Release" -DCMAKE_TOOLCHAIN_FILE=Toolchain-Emscripten.cmake src/"

Replace the src/ by the source directory.

I have not tried running this on the openjpeg project but I think this should put your on the right track. Iterate on this until it work. I have a working lib and exec using exactly this, no more ;-)

Again this is a CMAKE based project it looks nicely designed and looks modular, therefore I would stick with using CMAKE + cross compilation toolchain file and leave the details of make/emmake to ... CMAKE, unless you really have no other choice.

Hope this helps!

Romain

like image 166
rsacchettini Avatar answered Oct 07 '22 08:10

rsacchettini