Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake project for Emscripten

I want to make CMake and Emscripten friends. Didn't find more or less informative documentation on the Emscripten project website, but they provide CMake toolchain file so I think it should be possible. So far very basic compilation without advanced parameters works fine, but I have issues while using embind and preloading files.

  1. Linking process seems to miss Emscripten "binaries" and produces warnings for all embind related functions like this one: warning: unresolved symbol: _embind_register_class which results in respective errors while loading compiled JS file in rowser.
  2. No .data file is generated during the compilation.

I've created a minimalistic example which includes two targets: one "normal" (client) and one manual (manual-client) which simply runs emcc as I expect it to be run: https://github.com/xwaffelx/minimal-cmake-emscripten-project/blob/master/README.md

Although manual way works, I don't think it is a proper way to do it...

--- Update ---

As requested, here is even more short example:

  1. CMakeLists.txt file
    cmake_minimum_required(VERSION 2.8)
    cmake_policy(SET CMP0015 NEW)
    project(emtest)
    set(CMAKE_VERBOSE_MAKEFILE on)
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/build.emscripten)
    include_directories("lib/assimp/include")
    link_directories("lib/assimp/lib-js")
    link_libraries("assimp")
    file(GLOB_RECURSE CORE_HDR src/.h)
    file(GLOB_RECURSE CORE_SRC src/.cpp)
    add_definitions("-s DEMANGLE_SUPPORT=1 --preload-file ${CMAKE_SOURCE_DIR}/assets --bind")
    add_executable(client ${CORE_SRC} ${CORE_HDR})
    

Result should be equivalent to running the following command manualy:

emcc 
    -Ilib/assimp/include 
    -s DEMANGLE_SUPPORT=1
    --preload-file assets
    --bind
    Application.cpp 
    lib/assimp/lib-js/libassimp.so 
    -o client.js

Here is the Application.cpp:

#include "Application.h"

#include <iostream>

#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>

void Application::Initialize() {
    std::cout << "Initializing application." << std::endl;
    Assimp::Importer importer; // For test purpose
}

void Application::SayHello() {
    std::cout << "Hello!" << std::endl;
}

and Application.h:

#ifndef APPLICATION_H
#define APPLICATION_H

#include <emscripten/html5.h>
#include <emscripten/bind.h>

namespace e = emscripten;

class Application {
public:
    void Initialize();
    void SayHello();
};

EMSCRIPTEN_BINDINGS(EMTest) {
  e::class_<Application>("Application")
    .constructor()
      .function("Initialize", &Application::Initialize)
      .function("SayHello", &Application::SayHello);
}

#endif

THen I run cmake as follows: cmake -DCMAKE_TOOLCHAIN_PATH=path/to/Emscripten.cmake .. && make However, warnings like warning: unresolved symbol: _embind_register_class are produced during linking and running the code and no preloaded data in client.data file is created while compiling CMake project. At the same time no warnings and everything runs OK while compiling manually.

like image 712
Alexander Avatar asked Jun 10 '16 11:06

Alexander


People also ask

How do you build with Emscripten?

To build using Emscripten you need to replace gcc with emcc in your makefiles. This is done using emconfigure, which sets the appropriate environment variables like CXX (C++ compiler) and CC (the compiler).

What is Emcmake?

emcmake is a helper for cmake, setting various environment. variables so that emcc etc.

What happened to ASM JS?

asm. js is superseded by WebAssembly.


1 Answers

The solution was to specify all the flags during the linking by providing following CMake instruction: set_target_properties(client PROPERTIES LINK_FLAGS "-s DEMANGLE_SUPPORT=1 --preload-file assets --bind")

Thanks to developers of emscripten who helped in the github issues tracker.

like image 154
Alexander Avatar answered Sep 30 '22 08:09

Alexander