可以编译iostream库吗?

Can Emstripten compile the iostream library?

本文关键字:库吗 iostream 编译      更新时间:2023-09-26

我在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++程序成功编译。

首先,您的程序用emcc可以很好地编译。您的原始程序(使用printf)会使emcc假定它正在编译C代码,因此它会像C一样自动包含stdio.h。你的第二个程序有更多的麻烦,可能是由于安装错误(对我来说,我有一个这样的问题,因为我的LLVM版本不符合Emscripten需要的确切版本。)

不幸的是,我的理解是这是emscripten和自动安装程序(如apt-get)的常见问题——我在Mac上使用port和brew时都遇到了这个问题。

解决方案是通过SDK获得Emscripten,它将所有敏感部分捆绑在一起:https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html

仔细按照上面的说明去做。我遇到的两个问题是,它期望Python 2在您的系统上被称为python2,并且脚本将调整默认路径,假设您使用bash(如果您使用bash,它应该可以正常工作)