Noting to self, we need to create a doc page that instructs how to do cross-platform native+emscripten builds with cake, given that we have such an excellent cmake support.
Currently the best docs are here https://github.com/kripken/emscripten/blob/master/cmake/Modules/Platform/Emscripten.cmake except that one is better of using emcmake cmake instead of manually invoking cmake, so that if we need any changes to command-line params, we have an entry point in Emscripten side to inject those in.
As for examples, the test CMakeLists.txt files at https://github.com/kripken/emscripten/tree/master/tests/cmake are the best current examples.
@juj I was just using "emconfigure cmake
Not much. Both forms are supported, but emconfigure cmake (or emcmake cmake which is identical) also passes a CMake Module path on the command line and defaults to MinGW Generator - nothing that one couldn't also pass manually on the command line.
How to use it? Usually, you would call emcc src/index.cpp, but in CMake you have a _CMakeLists.txt_ that contains
add_executable(index src/index.cpp)
If I use emcmake cmake and emmake make it fails to build, since it tries to link
[ 50%] Building CXX object CMakeFiles/index.dir/src/index.cpp.o
[100%] Linking CXX executable bin/index.js
ERROR:root:CMakeFiles/index.dir/src/index.cpp.o: No such file or directory ("CMakeFiles/index.dir/src/index.cpp.o" was expected to be an input file, based on the commandline arguments provided)
That seems to be looking in the wrong directory. Do you see that as an Emscripten CMake specific issue, or CMake problem in general?
Check out https://github.com/kripken/emscripten/blob/master/tests/cmake/target_html/CMakeLists.txt#L7 which uses add_executable, by using a file(GLOB ...) to locate the source files.
I give a simple concrete example:
src/index.cpp
#include <iostream>
int main(int argc, char const *argv[])
{
std::cout << "hello world\n";
return 0;
}
I can compile this without errors using
emcc src/index.cpp -o index.html
Now I try to use CMake:
CMakeLists.txt
cmake_minimum_required(VERSION 3.5.1)
project(example)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -o index.html")
add_executable(index src/index.cpp)
I use a build directory inside my project root directory to compile:
$ mkdir build
$ cd build
$ emcmake cmake ..
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/project/build
$ emmake make
Scanning dependencies of target index
[ 50%] Building CXX object CMakeFiles/index.dir/src/index.cpp.o
[100%] Linking CXX executable index.js
ERROR:root:CMakeFiles/index.dir/src/index.cpp.o: No such file or directory ("CMakeFiles/index.dir/src/index.cpp.o" was expected to be an input file, based on the commandline arguments provided)
CMakeFiles/index.dir/build.make:95: recipe for target 'index.js' failed
make[2]: *** [index.js] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/index.dir/all' failed
make[1]: *** [CMakeFiles/index.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
_CMakeFiles/index.dir/src_ is an empty directory.
Is the correct invocation of cmake done this way:
emcmake cmake -DCMAKE_TOOLCHAIN_FILE="$EMSCRIPTEN_ROOT_PATH/cmake/Modules/Platform/Emscripten.cmake" ./path/to/src/tree
emcmake cmake --build .
Or is it:
emcmake cmake ./path/to/src/tree
emcmake cmake --build .
I couldn't find anything that specified whether the toolchain is passed into cmake with just emcmake. And whether emcmake should be used cmake --build which apparently abstracts over the generated builders.
I tried both and performed a directory diff, they are identical, so there's no need for -DCMAKE_TOOLCHAIN_FILE when using emcmake. Also found that emcmake cmake --build doesn't work at all, so really you can only do cmake --build . at the end. The final build results in lots of warnings about incompatible pointer types, but I think this is a consequence of the Cmake file forcing 32 bit pointers against source that was written with 64 bit pointers.
Another question I have is if you enable EMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=ON, the output from static build is .bc. However if another library which also uses cmake relies on this first library, will its CMake find the dependency correctly if .bc was generated and no .a nor .so (even though both the .a and .so should be llvm bitcode)? What cmake environment variables should be set?
See: https://github.com/kripken/emscripten/blob/master/cmake/Modules/Platform/Emscripten.cmake#L172
Also currently it defaults to making Release use -O2 optimisation. Is there a way to change this to an option command rather than a set command, so that optimisation flags can be overridden at the command line. Without this, it would require using ccmake to tweak the settings afterwards. Also I'm not sure but cmake has CMAKE_C_FLAGS, CMAKE_CXX_FLAGS, CMAKE_EXE_LINKER_FLAGS, CMAKE_SHARED_LINKER_FLAGS, CMAKE_MODULE_LINKER_FLAGS and CMAKE_STATIC_LINKER_FLAGS. Does the linker flags matter at all here? The emscripten docs says that we should be using the same optimisation level at each step and for each dependency.
Now I try to use CMake:
Sorry @maiermic, this comment slipped my attention when originally posted, only now @CMCDragonkai's added comments brought this to my attention. The issue in the presented example is that the line
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -o index.html")
is causing the trouble, because it steals CMake from being able to compile object code. When building with make VERBOSE=1, the command line shows the problem:
/Users/juj/emsdk/emscripten/incoming/em++ -o index.html -o CMakeFiles/index.dir/src/index.cpp.o -c /Users/juj/emsdk/emscripten/incoming/t/src/index.cpp
and two -o directives are causing the fault. (Curiously, see also #5555). The proper fix is to instead use the following CMake file:
cmake_minimum_required(VERSION 3.5.1)
project(example)
set(CMAKE_EXECUTABLE_SUFFIX ".html")
add_executable(index src/index.cpp)
which builds index.html appropriately.
Is the correct invocation of cmake done this way
Or is it:
Both ways will work, but the first one that explicitly passes the toolchain file is redundant, so
emcmake cmake ./path/to/src/tree
emcmake cmake --build .
should work. Also, I believe that
emcmake cmake ./path/to/src/tree
cmake --build .
should work as well, since configuration time is what sets up everything to the build. (If one of these forms is not working out ok, let's dig in deeper to understand why). If you are using e.g. Unix Makefiles generator, then
emcmake cmake ./path/to/src/tree
make
works as well, i.e. using an Emscripten wrapper directive during build should not be needed, it's only needed at cmake time.
Also found that emcmake cmake --build doesn't work at all, so really you can only do cmake --build . at the end.
If emcmake cmake --build . does not work, but cmake --build . does, then let's figure out why, I think both forms should be treated safe. Any clues or error logs as to why? Perhaps it's just a problem of positional input params going to wrong side of the -- delimiter. Try EMCC_DEBUG=1 or EM_BUILD_VERBOSE=3 env. var enabled builds to see more info.
Another question I have is if you enable EMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=ON, the output from static build is .bc. However if another library which also uses cmake relies on this first library, will its CMake find the dependency correctly if .bc was generated and no .a nor .so (even though both the .a and .so should be llvm bitcode)? What cmake environment variables should be set?
I belive that should work, but a current limitation is that the whole CMake script wide one will need to have the same option, i.e. some sub-CMake files can't build to .bc, and others to .a. Supporting that would probably need some target specific option to be added.
Also currently it defaults to making Release use -O2 optimisation. Is there a way to change this to an option command rather than a set command, so that optimisation flags can be overridden at the command line. Without this, it would require using ccmake to tweak the settings afterwards. Also I'm not sure but cmake has CMAKE_C_FLAGS, CMAKE_CXX_FLAGS, CMAKE_EXE_LINKER_FLAGS, CMAKE_SHARED_LINKER_FLAGS, CMAKE_MODULE_LINKER_FLAGS and CMAKE_STATIC_LINKER_FLAGS. Does the linker flags matter at all here? The emscripten docs says that we should be using the same optimisation level at each step and for each dependency.
We should aim to follow native Unix Makefiles builds here closely. I.e. how does this differ from native CMake builds with Unix Makefiles? If you have simple test cases to guide to focusing eyeballs to, I think we should adapt to align the behavior with native here. I can't quite remember why we force native builds to -O2 in CMake, perhaps because that was CMake default in native as well, and that was for some reason not getting applied to Emscripten builds, or something similar. If you are seeing discrepancies here in native vs CMake, let's look at those at a case basis.
The way to use emcmake cmake is very convinent and easy. after I looking into staic_lib project, I meet some problem. I use emcmake cmake -DSET_FAKE_SUFFIX_IN_PROJECT=1 .. to compile it, and change the CMakeLists.txt like this:
```cmake_minimum_required(VERSION 2.8)
project(static_library)
if (SET_FAKE_SUFFIX_IN_PROJECT)
set(CMAKE_STATIC_LIBRARY_SUFFIX ".js")
# Also check that we can control the prefix. Setting this to an empty string can be useful to get rid of the "lib" prefix that gets added by default.
set(CMAKE_STATIC_LIBRARY_PREFIX "myprefix_")
endif()
add_library(static_lib STATIC lib.cpp)
I originally think I will get some `js` script, like `emcc xxx -o run.js`. And could use it like:
Module.foo()
```
but it's not. so what should I do to get above result?
This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 7 days. Feel free to re-open at any time if this issue is still relevant.
Most helpful comment
Sorry @maiermic, this comment slipped my attention when originally posted, only now @CMCDragonkai's added comments brought this to my attention. The issue in the presented example is that the line
is causing the trouble, because it steals CMake from being able to compile object code. When building with
make VERBOSE=1, the command line shows the problem:and two
-odirectives are causing the fault. (Curiously, see also #5555). The proper fix is to instead use the following CMake file:which builds
index.htmlappropriately.