title: How do I compile C++11 code to webassembly?
body: <p>I've been trying to port the following code to webassembly: </p>
  
  <pre class="lang-cpp prettyprint-override"><code>#include "gmtl/gmtl/Vec.h"
  #include "gmtl/gmtl/VecOps.h"
  #include "gmtl/gmtl.h"
  #include &lt;vector&gt;
  #include &lt;random&gt;
  #include &lt;iostream&gt;
  #include &lt;chrono&gt; 
  #include &lt;map&gt;
  #include &lt;sstream&gt;
  #include &lt;ctime&gt;
  
  using namespace std;
  using namespace gmtl;
  
  class Settings{
    public:
      Settings(float _repulsion, float _epsilon, float _inner_distance, float _attraction, float _friction, float _gravity, float _min_start_pos, float _max_start_pos){
        repulsion = _repulsion;
        epsilon = _epsilon;
        inner_distance = _inner_distance;
        attraction = _attraction;
        friction = _friction;
        gravity = _gravity;
  
        min_start_pos = _min_start_pos;
        max_start_pos = _max_start_pos;
      }
  
      float repulsion;
      float epsilon;
      float inner_distance;
      float attraction;
      float friction;
      float gravity;
      float min_start_pos;
      float max_start_pos;
  };
  
  class Randomator {
    private:
      float min;
      float max;
  
    public:
      Randomator(){
        srand(time(NULL));
      }
  
      float get(){
        return rand() / (RAND_MAX + 1.0f);
      }
  };
  
  class Vertex {
    public:
  
      Vertex(int vertex_id){
        Randomator ra;
        position = gmtl::Vec3f(ra.get(), ra.get(), ra.get());
  
        id = vertex_id;
      }
  
      int id;
      gmtl::Vec3f position;
      gmtl::Vec3f velocity;
      gmtl::Vec3f acceleration;
  
      gmtl::Vec3f repulsion_forces;
      gmtl::Vec3f attraction_forces;
  
      static gmtl::Vec3f pairwise_repulsion(const gmtl::Vec3f&amp; one, const gmtl::Vec3f&amp; other, const Settings&amp; settings){
        gmtl::Vec3f diff = one - other;
        // gmtl::Vec3f diff = *(this-&gt;position) - *(other-&gt;position);
        float abs_diff = length(diff);
        return  (settings.repulsion / 
                 ((settings.epsilon + abs_diff)*(settings.epsilon + abs_diff)) * 
                 (diff / abs_diff));
      }
  
      bool operator==(const Vertex&amp; other){
        return other.id == id;
      }
  
      string toString(){
        stringstream ss;
        ss &lt;&lt; "Vertex " &lt;&lt; id;
        return ss.str();
      }
  };
  
  
  class Edge {
    public:
      Edge(int edge_id, Vertex* _source, Vertex* _target){
        source = _source;
        target = _target;
        id = edge_id;
      };
  
      int id;
      Vertex* source;
      Vertex* target;
      bool directed = false;
  
      string toString(){
        stringstream ss;
        ss &lt;&lt; "Edge " &lt;&lt; id;
        return ss.str();
      }
  
      bool operator==(const Edge&amp; other){
        return id == other.id;
      }
  };
  
  class BarnesHutNode3 {
    public:
      vector&lt;Vertex&gt; inners; // should probably be a pointer
      map&lt;string, BarnesHutNode3*&gt; outers;
      gmtl::Vec3f center_sum;
      int count;
      Settings settings;
  
      BarnesHutNode3(const Settings&amp; _settings) : settings(_settings){
        count = 0;
      }
  
      gmtl::Vec3f center(){
        return this-&gt;center_sum / (float)this-&gt;count;
      }
  
      void place_inner(Vertex&amp; vertex){
        this-&gt;inners.push_back(vertex);
        this-&gt;center_sum += vertex.position;
      }
  
      void place_outer(Vertex&amp; vertex){
        string octant = this-&gt;get_octant(vertex.position);
        this-&gt;outers[octant] = new BarnesHutNode3(settings);
        this-&gt;outers[octant]-&gt;insert(vertex);
      }
  
      void insert(Vertex&amp; vertex){
        if(this-&gt;inners.size() == 0){
          this-&gt;place_inner(vertex);
        }else{
          gmtl::Vec3f center = this-&gt;center();
          gmtl::Vec3f pos = vertex.position;
          float distance = sqrt((center[0] - pos[0])*(center[0] - pos[0]) + 
                               (center[1] - pos[1])*(center[1] - pos[1]) +
                               (center[2] - pos[2])*(center[2] - pos[2]));
  
          if(distance &lt;= settings.inner_distance){
            this-&gt;place_inner(vertex);
          }else{
            this-&gt;place_outer(vertex);
          }
        }
  
        this-&gt;count++;
      }
  
      string get_octant(gmtl::Vec3f&amp; position){
        gmtl::Vec3f center = this-&gt;center();
        string x = center[0] &lt; position[0] ? "l" : "r";
        string y = center[1] &lt; position[1] ? "u" : "d";
        string z = center[2] &lt; position[2] ? "i" : "o";
        return x+y+z;
      }
  
      void estimate(Vertex&amp; vertex, gmtl::Vec3f&amp; force, gmtl::Vec3f (*force_fn)(const gmtl::Vec3f&amp; p1, const gmtl::Vec3f&amp; p2, const Settings&amp; settings), const Settings&amp; settings){
        if(find(this-&gt;inners.begin(), this-&gt;inners.end(), vertex) != this-&gt;inners.end()){ // todo: make better, maintain a set or something
          for(auto i=0; i&lt;this-&gt;inners.size(); i++){
            if(this-&gt;inners[i].id != vertex.id){
              gmtl::Vec3f f = force_fn(vertex.position, this-&gt;inners[i].position, settings);
              force += f;
            }
          }
        }else{
          gmtl::Vec3f f = force_fn(vertex.position, this-&gt;center(), settings) * (float)this-&gt;inners.size();
          force += f;
        }
  
        for(auto &amp;it : this-&gt;outers){
          this-&gt;outers[it.first]-&gt;estimate(vertex, force, force_fn, settings);
        }
      }
  
      string toString(){
        return "BarnesHutNode3";
      }
  
      unsigned int size(){
        return this-&gt;count;
      }
  };
  
  class Graph {
    public:
      Graph(const Settings&amp; _settings) : settings(_settings){
        vertex_id = 0;
        edge_id = 0;
      };
  
      void add_vertex(const Vertex&amp; vertex){
        V.push_back(vertex);
      }
  
      void add_edge(const Edge&amp; edge){
        E.push_back(edge);
      }
  
      void remove_vertex(Vertex vertex){
        V.erase(find(V.begin(), V.end(), vertex));
      }
  
      void remove_edge(Edge edge){
        E.erase(find(E.begin(), E.end(), edge));
      }
  
      int vertex_id = 0;
      int edge_id = 0;
      vector&lt;Vertex&gt; V;
      vector&lt;Edge&gt; E;
      Settings settings;
  
      void layout(){
        // calculate repulsions
  
        BarnesHutNode3 tree(settings);
        for(Vertex&amp; vertex : this-&gt;V){
          tree.insert(vertex);
        }
        for(Vertex&amp; vertex : this-&gt;V){
          vertex.repulsion_forces = gmtl::Vec3f();
          tree.estimate(
            vertex,
            vertex.repulsion_forces,
            &amp;Vertex::pairwise_repulsion, 
            settings);
        }
  
        // calculate attractions 
        for(Edge edge : this-&gt;E){
          gmtl::Vec3f attraction = (edge.source-&gt;position - edge.target-&gt;position) * (-1 * settings.attraction);
          if(edge.directed){
            gmtl::Vec3f sp = edge.source-&gt;position;
            gmtl::Vec3f tp = edge.target-&gt;position;
  
            float distance = sqrt((sp[0] - tp[0])*(sp[0] - tp[0]) + 
                                        (sp[1] - tp[1])*(sp[1] - tp[1]) +
                                        (sp[2] - tp[2])*(sp[2] - tp[2]));
            gmtl::Vec3f gravity = gmtl::Vec3f(0.0f, settings.gravity/distance, 0.0f);
            edge.source-&gt;attraction_forces -= attraction;
            edge.target-&gt;attraction_forces += attraction;
          }
        }
  
        // update vertices
        for(Vertex&amp; vertex : this-&gt;V){
          gmtl::Vec3f friction = vertex.velocity * settings.friction;
          vertex.acceleration += vertex.repulsion_forces - vertex.attraction_forces - friction;
          vertex.velocity += vertex.acceleration;
          vertex.position += vertex.velocity;
        }
      }
  };
  
  
  gmtl::Vec3f avg_position(const Graph&amp;);
  vector&lt;gmtl::Vec3f&gt; average_positions(int, int, int, const Settings&amp;);
  
  class Experiment {
    public:
      Experiment(float&amp; _variable, const std::vector&lt;float&gt;&amp; _values, const Settings&amp; settings){
        variable = &amp;_variable;
        values = _values;
  
        for(auto value : values){
          *(this-&gt;variable) = value;
          this-&gt;histories.push_back(average_positions(50, 10, 30, settings));
        }
      }
  
      float* variable;
      std::vector&lt;float&gt; values;
      std::vector&lt;std::vector&lt;gmtl::Vec3f&gt; &gt; histories;
  
      static float length(gmtl::Vec3f v){
        return sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
      }
  
      static gmtl::Vec3f avg_position(const Graph&amp; graph){
        gmtl::Vec3f position;
        for(auto vertex : graph.V){
          position += vertex.position;
        }
        return position / (float)graph.V.size();
      }
  
      static std::vector&lt;gmtl::Vec3f&gt; average_positions(int iterations, int vertices, int edges, const Settings&amp; settings){
        vector&lt;gmtl::Vec3f&gt; history;
        Graph h(settings);
        for(int i=0; i&lt;vertices; i++){
          h.add_vertex(Vertex(i));
        }
        for(int i=0; i&lt;edges; i++){
          h.add_edge(Edge(i, &amp;h.V[rand() % h.V.size()], &amp;h.V[rand() % h.V.size()]));
        }
  
        for(int i=0; i&lt;iterations; i++){
          h.layout();
          cout &lt;&lt; ".";
          history.push_back(avg_position(h));
        }
  
        return history;
      }
  };
  
  class Main {
    public:
      static int run(int NUM_VERTICES, int NUM_EDGES){
        cout &lt;&lt; "Welcome to foud.cpp, the meat and bones of social cartography..." &lt;&lt; endl;
        float _repulsion = 5.0;
        float _epsilon = 0.1;
        float _inner_distance = 0.36;
        float _attraction = 0.0005;
        float _friction = 0.60;
        float _gravity = 10;
  
        float _min_start_pos = -1.0f;
        float _max_start_pos = 1.0f;
  
        srand(time(NULL));
  
        cout &lt;&lt; "Creating Randomator ... ";
        Randomator ra;
        cout &lt;&lt; "done." &lt;&lt; endl;
  
        cout &lt;&lt; "Creating Settings ... ";
        Settings settings(
          _repulsion, 
          _epsilon, 
          _inner_distance,
          _attraction,
          _friction,
          _gravity,
          _min_start_pos,
          _max_start_pos
        );
        cout &lt;&lt; "done." &lt;&lt; endl;
  
        cout &lt;&lt; "Creating graph ... ";
        Graph graph(settings);
        cout &lt;&lt; "done." &lt;&lt; endl;
  
        cout &lt;&lt; "Adding vertices ... ";
        for(int i=0; i&lt;NUM_VERTICES; i++){
          graph.add_vertex(Vertex(i));
        }
        cout &lt;&lt; "done." &lt;&lt; endl;
  
        cout &lt;&lt; "Adding edges ... ";
        for(int i=0; i&lt;NUM_EDGES; i++){
          Vertex source = graph.V[rand() % graph.V.size()];
          Vertex temp = graph.V[rand() % graph.V.size()];
          while(graph.V.size() &amp;&amp; temp.id != source.id){
            temp = graph.V[rand() % graph.V.size()];
          }
          Vertex target = temp;
          Edge edge(graph.edge_id++, &amp;source, &amp;target);
          graph.add_edge(edge);
        }
        cout &lt;&lt; "done." &lt;&lt; endl;
  
        cout &lt;&lt; "One layout step ... ";
        auto start = std::chrono::high_resolution_clock::now();
        graph.layout();
        auto stop = std::chrono::high_resolution_clock::now();
        cout &lt;&lt; "done." &lt;&lt; endl;
  
        auto dur = stop - start;
  
        cout &lt;&lt; NUM_VERTICES &lt;&lt; " vertices and " &lt;&lt; NUM_EDGES &lt;&lt; " edges took " &lt;&lt; (double)dur.count() &lt;&lt; "ms" &lt;&lt; endl;
        return 0;
      }
  };
  
  int main(int argc, char** argv){
    int v = 10000;
    int e = v*3;
    Main::run(v, e);
  }
  </code></pre>
  
  <p>I know the code isn't perfect, but it compiles using <code>clang++ -std=c++11 fourd.cpp</code>, but I can't find documentation on how to make clang compile to webassembly. </p>
  
  <p>I've tried looking far and wide, into the depths of google search terms, but couldn't find how to compile webassembly from c++11. I have clang installed, and nodejs, and I have pulled the emsdk.  </p>