Может ли Emstripten скомпилировать библиотеку iostream?

Я нахожусь на Ubuntu.

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.2 LTS
Release:    14.04
Codename:   trusty

Я установил Emscripten.

$ sudo apt-get install emscripten

Я написал следующую программу на C ++:

#include <iostream>

int main(){
printf("hello world\n");
}

Он компилируется, как и ожидалось.

$ emcc -O1 -s ASM_JS=1 main.cpp
$

Тем не менее, когда я пишу похожую программу, используя возможности iostream:

#include <iostream>

int main(){
std::cout << "hello world" << std::endl;
}

Не удается построить.

$ emcc -O1 -s ASM_JS=1 main.cpp
aborting from js compiler due to exception: unknown vector type <4 x i8> | undefined
aborting from js compiler due to exception: unknown vector type <4 x i8> | undefined
aborting from js compiler due to exception: unknown vector type <4 x i8> | undefined
Traceback (most recent call last):
File "/usr/share/emscripten/emscripten.py", line 1352, in <module>
_main(environ=os.environ)
File "/usr/share/emscripten/emscripten.py", line 1340, in _main
temp_files.run_and_clean(lambda: main(
File "/usr/share/emscripten/tools/tempfiles.py", line 39, in run_and_clean
return func()
File "/usr/share/emscripten/emscripten.py", line 1348, in <lambda>
DEBUG_CACHE=DEBUG_CACHE,
File "/usr/share/emscripten/emscripten.py", line 1235, in main
jcache=jcache, temp_files=temp_files, DEBUG=DEBUG, DEBUG_CACHE=DEBUG_CACHE)
File "/usr/share/emscripten/emscripten.py", line 292, in emscript
assert len(output) == 2, 'Did not receive forwarded data in an output - process failed? We only got: ' + output[0][-3000:]
AssertionError: Did not receive forwarded data in an output - process failed? We only got: ((HEAP32[(($1)>>2)])|0);
$3=((($2)-(12))|0);
$4=$3;
$5=((HEAP32[(($4)>>2)])|0);
$6=$this;
$_sum=((($5)+(24))|0);
$7=(($6+$_sum)|0);
$8=$7;
$9=((HEAP32[(($8)>>2)])|0);
$10=($9|0)==0;
if ($10) {
STACKTOP=sp;return (($this)|0);
}
$12=(($__s)|0);
HEAP8[($12)]=0;
$13=(($__s+4)|0);
HEAP32[(($13)>>2)]=$this;
$_sum_i=((($5)+(16))|0);
$14=(($6+$_sum_i)|0);
$15=$14;
$16=((HEAP32[(($15)>>2)])|0);
$17=($16|0)==0;
do {
if ($17) {
$_sum1_i=((($5)+(72))|0);
$19=(($6+$_sum1_i)|0);
$20=$19;
$21=((HEAP32[(($20)>>2)])|0);
$22=($21|0)==0;
if (!($22)) {
$24=((__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5flushEv($21))|0);
}
HEAP8[($12)]=1;
$26=((HEAP32[(($1)>>2)])|0);
$27=((($26)-(12))|0);
$28=$27;
$29=((HEAP32[(($28)>>2)])|0);
$_sum1=((($29)+(24))|0);
$30=(($6+$_sum1)|0);
$31=$30;
$32=((HEAP32[(($31)>>2)])|0);
$33=$32;
$34=$32;
$35=((HEAP32[(($34)>>2)])|0);
$36=(($35+24)|0);
$37=((HEAP32[(($36)>>2)])|0);
$38=((FUNCTION_TABLE_ii[($37)&{{{ FTM_ii }}}]($33))|0);
$39=($38|0)==-1;
if (!($39)) {
break;
}
$41=((HEAP32[(($1)>>2)])|0);
$42=((($41)-(12))|0);
$43=$42;
$44=((HEAP32[(($43)>>2)])|0);
$45=(($6+$44)|0);
$46=$45;
$_sum2=((($44)+(16))|0);
$47=(($6+$_sum2)|0);
$48=$47;
$49=((HEAP32[(($48)>>2)])|0);
$50=$49|1;
__ZNSt3__18ios_base5clearEj($46,$50);
}
} while(0);
__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryD2Ev($__s);
STACKTOP=sp;return (($this)|0);
}function __ZNSt3__18ios_base33__set_badbit_and_consider_rethrowEv($this){
$this=($this)|0;
var $1=0,$2=0,$3=0,$4=0,$5=0,$6=0,$7=0,label=0;

$1=(($this+16)|0);
$2=((HEAP32[(($1)>>2)])|0);
$3=$2|1;
HEAP32[(($1)>>2)]=$3;
$4=(($this+20)|0);
$5=((HEAP32[(($4)>>2)])|0);
$6=$5&1;
$7=($6|0)==0;
if ($7) {
return;
} else {
___cxa_rethrow();

}
}function __ZNSt3__113basic_istreamIwNS_11char_traitsIwEEED0Ev($this){
$this=($this)|0;
var $1=0,$2=0,label=0;

$1=(($this+8)|0);
__ZNSt3__18ios_baseD2Ev($1);
$2=$this;
__ZdlPv($2);
return;
}function __ZNSt3__113basic_istreamIwNS_11char_traitsIwEEED1Ev($this){
$this=($this)|0;
var $1=0,label=0;

$1=(($this+8)|0);
__ZNSt3__18ios_baseD2Ev($1);
return;
}function __ZTv0_n12_NSt3__113basic_istreamIwNS_11char_traitsIwEEED0Ev($this){
$this=($this)|0;
var $1=0,$2=0,$3=0,$4=0,$5=0,$6=0,$7=0,$_sum=0,$8=0,$9=0,label=0;

$1=$this;
$2=$this;
$3=((HEAP32[(($2)>>2)])|0);
$4=((($3)-(12))|0);
$5=$4;
$6=((HEAP32[(($5)>>2)])|0);
$7=(($1+$6)|0);
$_sum=((($6)+(8))|0);
$8=(($1+$_sum)|0);
$9=$8;
__ZNSt3__18ios_baseD2Ev($9);
__ZdlPv($7);
return;
}function __ZTv0_n12_NSt3__113basic_istreamIwNS_11char_traitsIwEEED1Ev($this){
$this=($this)|0;
var $1=0,$2=0,$3=0,$4=0,$5=0,$6=0,$_sum=0,$7=0,$8=0,label=0;

$1=$this;
$2=$this;
$3=((HEAP32[(($2)>>2)])|0);
$4=((($3)-(12))|0);
$5=$4;
$6=((HEAP32[(($5)>>2)])|0);
$_sum=((($6)+(8))|0);
$7=(($1+$_sum)|0);
$8=$7;
__ZNSt3__18ios_baseD2Ev($8);
return;
}Traceback (most recent call last):
File "/usr/bin/emcc", line 1864, in <module>
final = shared.Building.emscripten(final, append_ext=False, extra_args=extra_args)
File "/usr/share/emscripten/tools/shared.py", line 1276, in emscripten
assert os.path.exists(filename + '.o.js') and len(open(filename + '.o.js', 'r').read()) > 0, 'Emscripten failed to generate .js: ' + str(compiler_output)
AssertionError: Emscripten failed to generate .js:

У меня сложилось впечатление, что Emscripten прошел долгий путь и способен собрать целые игры на C ++ для браузера! Есть ли какой-то флаг или конфигурация, которые я пропустил, чтобы успешно скомпилировать части стандартной библиотеки C ++? Я знаю, что компиляторы clang / gcc по умолчанию будут ссылаться на стандартную разделяемую библиотеку C ++. Проблема как-то связана с тем, что вы думаете?

Я также попытался с помощью команды em++ на месте emcc и получил то же сообщение об ошибке.


Если уместно, вот конфигурация по умолчанию, которая была создана при первом запуске emscripten:

$ cat ~/.emscripten

# Note: If you put paths relative to the home directory, do not forget os.path.expanduser

import os

# this helps projects using emscripten find it
EMSCRIPTEN_ROOT = os.path.expanduser(os.getenv('EMSCRIPTEN') or '/usr/share/emscripten') # directory
LLVM_ROOT = os.path.expanduser(os.getenv('LLVM') or '/usr/bin') # directory
PYTHON = os.path.expanduser(os.getenv('PYTHON') or '/usr/bin/python2') # executable

# See below for notes on which JS engine(s) you need
NODE_JS = os.path.expanduser(os.getenv('NODE') or '/usr/bin/node') # executable
SPIDERMONKEY_ENGINE = [os.path.expanduser(os.getenv('SPIDERMONKEY') or 'js')] # executable
V8_ENGINE = os.path.expanduser(os.getenv('V8') or 'd8') # executable

JAVA = 'java' # executable

TEMP_DIR = '/tmp'

CRUNCH = os.path.expanduser(os.getenv('CRUNCH') or 'crunch') # executable

#CLOSURE_COMPILER = '..' # define this to not use the bundled version

######################################################################################################### Pick the JS engine to use for running the compiler. This engine must exist, or
# nothing can be compiled.
#
# Recommendation: If you already have node installed, use that. Otherwise, build v8 or
#                 spidermonkey from source. Any of these three is fine, as long as it's
#                 a recent version (especially for v8 and spidermonkey).

COMPILER_ENGINE = NODE_JS
#COMPILER_ENGINE = V8_ENGINE
#COMPILER_ENGINE = SPIDERMONKEY_ENGINE# All JS engines to use when running the automatic tests. Not all the engines in this list
# must exist (if they don't, they will be skipped in the test runner).
#
# Recommendation: If you already have node installed, use that. If you can, also build
#                 spidermonkey from source as well to get more test coverage (node can't
#                 run all the tests due to node issue 1669). v8 is currently not recommended
#                 here because of v8 issue 1822.

JS_ENGINES = [NODE_JS] # add this if you have spidermonkey installed too, SPIDERMONKEY_ENGINE]

Кажется, я не могу найти способ заставить базовую программу C ++ выше успешно компилироваться.

0

Решение

Во-первых, ваша программа прекрасно компилируется для меня с помощью emcc. Ваша оригинальная программа (с printf) заставляет emcc предполагать, что она компилирует код C и поэтому автоматически включает stdio.h, как это делает C. У вашей второй программы больше проблем, возможно, из-за ошибки установки (у меня была такая проблема, потому что моя версия LLVM не совпадает с точной версией Emscripten).

К сожалению, я понимаю, что это обычная проблема для emscripten и автоинсталляторов, таких как apt-get — у меня была проблема с портом и brew на моем Mac.

Решение состоит в том, чтобы получить Emscripten через SDK, который объединяет все чувствительные части: https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html

Следуйте инструкциям там тщательно. Две проблемы, с которыми я столкнулся, заключались в том, что он ожидает вызова Python 2 python2 в вашей системе и в скрипте для настройки пути по умолчанию предполагается, что вы используете bash (если это так, он должен работать нормально).

1

Другие решения