Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save netpoetica/28ce31478cfc43edcaa7 to your computer and use it in GitHub Desktop.
Save netpoetica/28ce31478cfc43edcaa7 to your computer and use it in GitHub Desktop.
Compiling v8 and Hello, World Example on Mac OSX Mavericks (10.9.4), Link Clang to Static Libraries, properly configure your environment for v8 build

Compiling v8 and Hello, World Example on Mac OSX Mavericks (10.9.4)

by Keith Rosenberg (netpoetica)

Note: do this in some sort of project/ directory that makes sense. depot_tools are going to need to be in your path, so you may want to install them somewhere you are comfortable with.

1) Get the v8 source

git clone https://github.com/v8/v8.git

2) Install depot tools

Note: you can read about depot_tools here

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

additionally, the path to depot tools must be available in your PATH, so add it to your ~/.zshrc or ~/.bashrc file

cd depot_tools
pwd
// should print ~/Desktop/git/depot_tools or the like
vim ~/.zshrc
// or .bashrc

// Add it to the path or add this line at the bottom of your file
export PATH=~/Desktop/git/depot_tools:"$PATH"

3) Add gyp and c/c++/linking configuration to your environment

First make sure clang and clang++ are in in your PATH by running

which clang && which clang++

If for some reason you do not have clang available, make sure you have the most recent Xcode command line tools installed.

vim ~/.zshrc

and add the following:

export CXX="`which clang++`"
export CC="`which clang`"
export CPP="`which clang` -E"
export LINK="`which clang++`"
export CXX_host="`which clang++`"
export CC_host="`which clang`"
export CPP_host="`which clang` -E"
export LINK_host="`which clang++`"
export GYP_DEFINES="clang=1"

4) Install node gyp

In the command line, in the v8 folder, run

make builddeps

it's worth noting that some documentation says to run

make dependencies

from what I can tell, they both install gyp, but make dependencies installs some third party tools you may eventually need. So either one should work, but go ahead and run both if you want (I did) - it won't hurt anything.

5) Finally, run make to create static libs for linking

Now the juicy part. In the v8 folder, you'll have to run make. v8's make lets you specify your architecture and number of cores.

However, your best bet is to let make figure out which architecture to build for your machine. If you know how many cores you have for your CPU, there is a command you can use to specify that.

If you open Activity Monitor, and then navigate to Window -> CPU Usage, the visual will pop up that looks like a bar graph. However many bars there are, that is how many cores you have.

On my machine, I have four, so I would run

make native -j 4

However, if you are unsure, just run

make native

This may take a while (on a kind-of-crap MacBook Pro, takes about 10 minutes).

6) Now, copy the hello world example below into a new file in the v8 folder (direct child of v8 folder) and save it as hello_world.cpp

#include <v8.h>

using namespace v8;

int main(int argc, char* argv[]) {
  // Create a new Isolate and make it the current one.
  Isolate* isolate = Isolate::New();
  Isolate::Scope isolate_scope(isolate);

  // Create a stack-allocated handle scope.
  HandleScope handle_scope(isolate);

  // Create a new context.
  Local<Context> context = Context::New(isolate);

  // Enter the context for compiling and running the hello world script.
  Context::Scope context_scope(context);

  // Create a string containing the JavaScript source code.
  Local<String> source = String::NewFromUtf8(isolate, "'Hello' + ', World!'");

  // Compile the source code.
  Local<Script> script = Script::Compile(source);

  // Run the script to get the result.
  Local<Value> result = script->Run();

  // Convert the result to an UTF8 string and print it.
  String::Utf8Value utf8(result);
  printf("%s\n", *utf8);
  return 0;
}

7) Finally, you're ready to compile and see hello_world.cpp's output!

In terminal,in the v8/ folder, run

clang++ -Iinclude out/native/libv8_base.a out/native/libv8_libbase.a out/native/libv8_snapshot.a out/native/libicudata.a out/native/libicuuc.a out/native/libicui18n.a hello_world.cpp -o hello_world 

viola! You're now ready to start messing with v8!

Resources

Google's Getting Started Guide

Installing depot_tools

About depot_tools - in depth

Using Git to Keep v8 Up to Date

The Difference Between make builddeps and make dependencies

// From https://developers.google.com/v8/get_started
#include <v8.h>
using namespace v8;
int main(int argc, char* argv[]) {
// Create a new Isolate and make it the current one.
Isolate* isolate = Isolate::New();
Isolate::Scope isolate_scope(isolate);
// Create a stack-allocated handle scope.
HandleScope handle_scope(isolate);
// Create a new context.
Local<Context> context = Context::New(isolate);
// Enter the context for compiling and running the hello world script.
Context::Scope context_scope(context);
// Create a string containing the JavaScript source code.
Local<String> source = String::NewFromUtf8(isolate, "'Hello' + ', World!'");
// Compile the source code.
Local<Script> script = Script::Compile(source);
// Run the script to get the result.
Local<Value> result = script->Run();
// Convert the result to an UTF8 string and print it.
String::Utf8Value utf8(result);
printf("%s\n", *utf8);
return 0;
}
@matthova
Copy link

I've tried these instructions multiple times with no success. I thought maybe copying the single quote ` vs ' character was causing a problem, and tried both ways.

FWIW this is what I'm running into:

$my_v8_folder: v8 matthova$ clang++ -Iinclude out/native/libv8_base.a out/native/libv8_libbase.a out/native/libv8_snapshot.a out/native/libicudata.a out/native/libicuuc.a out/native/libicui18n.a hello_world.cpp -o hello_world
Undefined symbols for architecture x86_64:
"std::string::_Rep::_M_destroy(std::allocator const&)", referenced from:
v8::internal::Profiler::Engage() in libv8_base.a(log.o)
v8::base::OS::GetSharedLibraryAddresses() in libv8_libbase.a(platform-macos.o)
std::vector<v8::base::OS::SharedLibraryAddress, std::allocatorv8::base::OS::SharedLibraryAddress >::_M_insert_aux(__gnu_cxx::__normal_iterator<v8::base::OS::SharedLibraryAddress*, std::vector<v8::base::OS::SharedLibraryAddress, std::allocatorv8::base::OS::SharedLibraryAddress > >, v8::base::OS::SharedLibraryAddress const&) in libv8_libbase.a(platform-macos.o)
"std::string::_Rep::_S_empty_rep_storage", referenced from:
v8::internal::Profiler::Engage() in libv8_base.a(log.o)
v8::base::OS::GetSharedLibraryAddresses() in libv8_libbase.a(platform-macos.o)
std::vector<v8::base::OS::SharedLibraryAddress, std::allocatorv8::base::OS::SharedLibraryAddress >::_M_insert_aux(__gnu_cxx::__normal_iterator<v8::base::OS::SharedLibraryAddress*, std::vector<v8::base::OS::SharedLibraryAddress, std::allocatorv8::base::OS::SharedLibraryAddress > >, v8::base::OS::SharedLibraryAddress const&) in libv8_libbase.a(platform-macos.o)
"std::string::assign(std::string const&)", referenced from:
std::vector<v8::base::OS::SharedLibraryAddress, std::allocatorv8::base::OS::SharedLibraryAddress >::_M_insert_aux(__gnu_cxx::_normal_iterator<v8::base::OS::SharedLibraryAddress*, std::vector<v8::base::OS::SharedLibraryAddress, std::allocatorv8::base::OS::SharedLibraryAddress > >, v8::base::OS::SharedLibraryAddress const&) in libv8_libbase.a(platform-macos.o)
"std::basic_string<char, std::char_traits, std::allocator >::basic_string(char const
, std::allocator const&)", referenced from:
v8::base::OS::GetSharedLibraryAddresses() in libv8_libbase.a(platform-macos.o)
"std::basic_string<char, std::char_traits, std::allocator >::basic_string(std::string const&)", referenced from:
v8::base::OS::GetSharedLibraryAddresses() in libv8_libbase.a(platform-macos.o)
std::vector<v8::base::OS::SharedLibraryAddress, std::allocatorv8::base::OS::SharedLibraryAddress >::_M_insert_aux(__gnu_cxx::_normal_iterator<v8::base::OS::SharedLibraryAddress, std::vector<v8::base::OS::SharedLibraryAddress, std::allocatorv8::base::OS::SharedLibraryAddress > >, v8::base::OS::SharedLibraryAddress const&) in libv8_libbase.a(platform-macos.o)
"std::_Rb_tree_decrement(std::Rb_tree_node_base)", referenced from:
std::Rb_tree<unsigned char, std::pair<unsigned char* const, v8::internal::AddressToTraceMap::RangeStack>, std::_Select1st<std::pair<unsigned char* const, v8::internal::AddressToTraceMap::RangeStack> >, std::less<unsigned char*>, std::allocator<std::pair<unsigned char* const, v8::internal::AddressToTraceMap::RangeStack> > >::_M_insert_unique(std::pair<unsigned char* const, v8::internal::AddressToTraceMap::RangeStack> const&) in libv8_base.a(allocation-tracker.o)
std::_Rb_treev8::internal::Handle<v8::internal::Map, v8::internal::Handlev8::internal::Map, std::_Identityv8::internal::Handle<v8::internal::Map >, std::lessv8::internal::Handle<v8::internal::Map >, v8::internal::zone_allocatorv8::internal::Handle<v8::internal::Map > >::_M_insert_unique(v8::internal::Handlev8::internal::Map const&) in libv8_base.a(lithium-codegen.o)
"std::Rb_tree_increment(std::Rb_tree_node_base const)", referenced from:
v8::internal::LChunk::CommitDependencies(v8::internal::Handlev8::internal::Code) const in libv8_base.a(lithium.o)
v8::internal::LChunk::Codegen() in libv8_base.a(lithium.o)
"std::Rb_tree_increment(std::Rb_tree_node_base)", referenced from:
v8::internal::AddressToTraceMap::RemoveRange(unsigned char
, unsigned char
) in libv8_base.a(allocation-tracker.o)
v8::internal::AddressToTraceMap::Print() in libv8_base.a(allocation-tracker.o)
"std::_throw_length_error(char const)", referenced from:
std::vector<v8::base::OS::SharedLibraryAddress, std::allocatorv8::base::OS::SharedLibraryAddress >::_M_insert_aux(__gnu_cxx::_normal_iterator<v8::base::OS::SharedLibraryAddress, std::vector<v8::base::OS::SharedLibraryAddress, std::allocatorv8::base::OS::SharedLibraryAddress > >, v8::base::OS::SharedLibraryAddress const&) in libv8_libbase.a(platform-macos.o)
"std::Rb_tree_rebalance_for_erase(std::Rb_tree_node_base, std::Rb_tree_node_base&)", referenced from:
v8::internal::AddressToTraceMap::RemoveRange(unsigned char
, unsigned char
) in libv8_base.a(allocation-tracker.o)
"std::_Rb_tree_insert_and_rebalance(bool, std::Rb_tree_node_base, std::Rb_tree_node_base, std::_Rb_tree_node_base&)", referenced from:
std::Rb_tree<unsigned char, std::pair<unsigned char* const, v8::internal::AddressToTraceMap::RangeStack>, std::_Select1st<std::pair<unsigned char* const, v8::internal::AddressToTraceMap::RangeStack> >, std::less<unsigned char*>, std::allocator<std::pair<unsigned char* const, v8::internal::AddressToTraceMap::RangeStack> > >::_M_insert_unique(std::pair<unsigned char* const, v8::internal::AddressToTraceMap::RangeStack> const&) in libv8_base.a(allocation-tracker.o)
std::_Rb_treev8::internal::Handle<v8::internal::Map, v8::internal::Handlev8::internal::Map, std::_Identityv8::internal::Handle<v8::internal::Map >, std::lessv8::internal::Handle<v8::internal::Map >, v8::internal::zone_allocatorv8::internal::Handle<v8::internal::Map > >::_M_insert_unique(v8::internal::Handlev8::internal::Map const&) in libv8_base.a(lithium-codegen.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

@jwilm
Copy link

jwilm commented Aug 22, 2014

@matthova: Try linking against libstdc++ instead of libc++ which is default with clang. Just add -stdlib=libstdc++ to your clang++ call.

@Archiboldian
Copy link

I got this error upon running the successfully compiled hello_world.cpp:

# Fatal error in ../src/isolate.cc, line 1655
# CHECK(thread_data_table_) failed

I found out (thanks to this thread https://code.google.com/p/v8/issues/detail?id=3627) that due to a relatively recent change to the V8 library, V8 requires initialisation prior to it being used. All that this entails is adding V8::Initialize() at the beginning of the main function.

Here's a modified version of hello_world.cpp that works with stable V8 (v 3.29.59) at time of posting:

// From https://developers.google.com/v8/get_started
#include <v8.h>

using namespace v8;

int main(int argc, char* argv[]) {
  // Need to initialise V8 before anything else.
  V8::Initialize();

  // Create a new Isolate and make it the current one.
  Isolate* isolate = Isolate::New();
  Isolate::Scope isolate_scope(isolate);

  // Create a stack-allocated handle scope.
  HandleScope handle_scope(isolate);

  // Create a new context.
  Local<Context> context = Context::New(isolate);

  // Enter the context for compiling and running the hello world script.
  Context::Scope context_scope(context);

  // Create a string containing the JavaScript source code.
  Local<String> source = String::NewFromUtf8(isolate, "'Hello' + ', World!'");

  // Compile the source code.
  Local<Script> script = Script::Compile(source);

  // Run the script to get the result.
  Local<Value> result = script->Run();

  // Convert the result to an UTF8 string and print it.
  String::Utf8Value utf8(result);
  printf("%s\n", *utf8);
  return 0;
}

Hope this helps someone out. :)

@jeroen
Copy link

jeroen commented Nov 25, 2014

Anyone has instructions for compiling against the brew install v8 libs?

@netpoetica
Copy link
Author

@jeroenooms I have never had any luck with v8 installed via brew, thats why I ended up going through all this hassle to write these instructions :-)

@zelid
Copy link

zelid commented May 21, 2015

Thanks! Worked fine on OS X 10.10.3 beside make dependencies

@thlorenz
Copy link

Updated this for latest v8 in this project.
Requires clang++.

Steps explained in Usage.
v8 fetch and build implemented in v8.mk
Building examples and linking in v8 statics implemented in .common.mk.
Note, building in Debug mode with ninja.

@kirankashalkar
Copy link

Thanks to @jwlim and @Archiboldian for those troubleshooting instructions

@xaxxon
Copy link

xaxxon commented Dec 22, 2015

Any chance of getting an updated guide? The -stdlib=libstdc++ is pretty important and the source code no longer compiles:

error: too few arguments to function call, single argument 'params' was not specified Isolate* isolate = Isolate::New(); ~~~~~~~~~~~~ ^ ./include/v8.h:5430:3: note: 'New' declared here static Isolate* New(const CreateParams& params);

Copying the .bin files from the v8 build directory is also required or your Isolate crashes.

Here's the compiler command that I eventually got to work:

clang++ -stdlib=libstdc++ -std=c++11 -I. hello_world.cpp -o h2 out/x64.release/libv8_base.a out/x64.release/libv8_libbase.a out/x64.release/libicudata.a out/x64.release/libicuuc.a out/x64.release/libicui18n.a out/x64.release/libv8_base.a out/x64.release/libv8_external_snapshot.a out/x64.release/libv8_libplatform.a

using the source code from here:

https://developers.google.com/v8/get_started

@primIl
Copy link

primIl commented Apr 8, 2016

For reference, I've managed to compile it easily with homebrew-installed v8 (I am running OS X 10.10):
brew install v8
clang++ -std=c++11 -I/usr/local/opt/v8 /usr/local/opt/v8/lib/*.a hello_world.cpp -o hello_world

@juliusl
Copy link

juliusl commented Aug 3, 2016

Can confirm on macOS 10.11.5, however didn't use the hello_world.cpp in this gist. Used it from here: https://developers.google.com/v8/get_started.

Copy link

ghost commented Oct 14, 2018

make: *** No rule to make target `dependencies'. Stop.

make: *** No rule to make target `builddeps'. Stop.

@jianmin-zhao
Copy link

Please help: cannot find Makefile in V8 source directory

@fernandes
Copy link

@jeroen @netpoetica after 6 years it probably won't help, but maybe for someone in the future

I'm running macos 10.15

⌁ brew info v8   
v8: stable 8.7.220.29 (bottled)
g++ -I /usr/local/Cellar/v8/8.7.220.29/libexec -I /usr/local/Cellar/v8/8.7.220.29/libexec/include -L /usr/local/Cellar/v8/8.7.220.29/libexec/ main.cc -o hello_world -lv8 -lv8_libbase -lv8_libplatform -lv8 -licuuc -licui18n -stdlib=libc++ -std=c++11 -DV8_COMPRESS_POINTERS

did the trick 😉

./hello_world 
Hello, World!
3 + 4 = 7

I got the sample from master on this link the commit hash is 6e506475e451824338fa8f959b502c710c8aaeed

hope it helps

@liujiangfeng
Copy link

but, how to debug v8 source code ?
in mac , i can not do this, only get the result of code run

@liujiangfeng
Copy link

i try it, use many method, i m upset

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment