Research on compiling nodejs and its source code, and compile nodejs source code
This article will study the principle and nature of nodejs from the source code, explore nodejs application scenarios, and high-performance development practices guide.
Directory:
Section 1: Compile node. js
Section 2: Source Code Analysis
Enter the topic: the following is done in win7 64. For compilation on other platforms, see the official website.
Section 1: Compile node. js. The process is very simple.
1. Download the source code. Git clone https://github.com/joyent/node
If the git client is not installed, you can click Download ZIP on the https://github.com/joyent/node to Download
2. Install Python 2.6 or 2.7 and Visual Studio 2010 or 2012. Here are Python 2.7.8 and Visual Studio 2012.
3. Go to the node directory and execute vcbuild release.
The compilation is successful in more than 10 minutes, and node.exe will be generated in the releasedirectory. The following figure shows the successful compilation.
Section 2: Source Code Analysis
Open the node directory in IDE to help us look at the source code. Here is Idea.
Benchmark: Some nodejs performance test code
Build: Compile nodejs to generate a directory
Debug: Compile nodejs to generate a directory
Release: Compile nodejs to generate a directory
Deps: nodejs dependent toolkit, including v8, http_parser, opensslzlib, zlib, and uv...
Doc: Document
Lib: Contains JavaScript source code.
Src: contains the C ++ source code.
Test: test code
Tools: tools used during compilation
Here we only need to pay attention to the src and lib folders.
1. view the node process startup process from the node. cc File
int Start(int argc, char** argv) { const char* replaceInvalid = getenv("NODE_INVALID_UTF8"); if (replaceInvalid == NULL) WRITE_UTF8_FLAGS |= String::REPLACE_INVALID_UTF8;#if !defined(_WIN32) // Try hard not to lose SIGUSR1 signals during the bootstrap process. InstallEarlyDebugSignalHandler();#endif assert(argc > 0); // Hack around with the argv pointer. Used for process.title = "blah". argv = uv_setup_args(argc, argv); // This needs to run *before* V8::Initialize(). The const_cast is not // optional, in case you're wondering. int exec_argc; const char** exec_argv; Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);#if HAVE_OPENSSL // V8 on Windows doesn't have a good source of entropy. Seed it from // OpenSSL's pool. V8::SetEntropySource(crypto::EntropySource);#endif int code; V8::Initialize(); { Locker locker(node_isolate); Isolate::Scope isolate_scope(node_isolate); HandleScope handle_scope(node_isolate); Local<Context> context = Context::New(node_isolate); Environment* env = CreateEnvironment( node_isolate, context, argc, argv, exec_argc, exec_argv); // Assign env to the debugger's context if (debugger_running) { HandleScope scope(env->isolate()); env->AssignToContext(v8::Debug::GetDebugContext()); } // This Context::Scope is here so EnableDebug() can look up the current // environment with Environment::GetCurrent(). // TODO(bnoordhuis) Reorder the debugger initialization logic so it can // be removed. { Context::Scope context_scope(env->context()); bool more; do { more = uv_run(env->event_loop(), UV_RUN_ONCE); if (more == false) { EmitBeforeExit(env); // Emit `beforeExit` if the loop became alive either after emitting // event, or after running some callbacks. more = uv_loop_alive(env->event_loop()); if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0) more = true; } } while (more == true); code = EmitExit(env); RunAtExit(env); } env->Dispose(); env = NULL; } CHECK_NE(node_isolate, NULL); node_isolate->Dispose(); node_isolate = NULL; V8::Dispose(); delete[] exec_argv; exec_argv = NULL; return code;}
Environment* CreateEnvironment(Isolate* isolate, Handle<Context> context, int argc, const char* const* argv, int exec_argc, const char* const* exec_argv) { HandleScope handle_scope(isolate); Context::Scope context_scope(context); Environment* env = Environment::New(context); uv_check_init(env->event_loop(), env->immediate_check_handle()); uv_unref( reinterpret_cast<uv_handle_t*>(env->immediate_check_handle())); uv_idle_init(env->event_loop(), env->immediate_idle_handle()); // Inform V8's CPU profiler when we're idle. The profiler is sampling-based // but not all samples are created equal; mark the wall clock time spent in // epoll_wait() and friends so profiling tools can filter it out. The samples // still end up in v8.log but with state=IDLE rather than state=EXTERNAL. // TODO(bnoordhuis) Depends on a libuv implementation detail that we should // probably fortify in the API contract, namely that the last started prepare // or check watcher runs first. It's not 100% foolproof; if an add-on starts // a prepare or check watcher after us, any samples attributed to its callback // will be recorded with state=IDLE. uv_prepare_init(env->event_loop(), env->idle_prepare_handle()); uv_check_init(env->event_loop(), env->idle_check_handle()); uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle())); uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle())); if (v8_is_profiling) { StartProfilerIdleNotifier(env); } Local<FunctionTemplate> process_template = FunctionTemplate::New(isolate); process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process")); Local<Object> process_object = process_template->GetFunction()->NewInstance(); env->set_process_object(process_object); SetupProcessObject(env, argc, argv, exec_argc, exec_argv); Load(env); return env;}
void SetupProcessObject(Environment* env, int argc, const char* const* argv, int exec_argc, const char* const* exec_argv) { HandleScope scope(env->isolate()); Local<Object> process = env->process_object(); process->SetAccessor(env->title_string(), ProcessTitleGetter, ProcessTitleSetter); // process.version READONLY_PROPERTY(process, "version", FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION)); // process.moduleLoadList READONLY_PROPERTY(process, "moduleLoadList", env->module_load_list_array()); // process.versions Local<Object> versions = Object::New(env->isolate()); READONLY_PROPERTY(process, "versions", versions); const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR) "." NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR); READONLY_PROPERTY(versions, "http_parser", FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version)); // +1 to get rid of the leading 'v' READONLY_PROPERTY(versions, "node", OneByteString(env->isolate(), NODE_VERSION + 1)); READONLY_PROPERTY(versions, "v8", OneByteString(env->isolate(), V8::GetVersion())); READONLY_PROPERTY(versions, "uv", OneByteString(env->isolate(), uv_version_string())); READONLY_PROPERTY(versions, "zlib", FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION)); const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION); READONLY_PROPERTY( versions, "modules", FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));
void Load(Environment* env) { HandleScope handle_scope(env->isolate()); // Compile, execute the src/node.js file. (Which was included as static C // string in node_natives.h. 'natve_node' is the string containing that // source code.) // The node.js file returns a function 'f' atexit(AtExit); TryCatch try_catch; // Disable verbose mode to stop FatalException() handler from trying // to handle the exception. Errors this early in the start-up phase // are not safe to ignore. try_catch.SetVerbose(false); Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(), "node.js"); Local<Value> f_value = ExecuteString(env, MainSource(env), script_name); if (try_catch.HasCaught()) { ReportException(env, try_catch); exit(10); } assert(f_value->IsFunction()); Local<Function> f = Local<Function>::Cast(f_value); // Now we call 'f' with the 'process' variable that we've built up with // all our bindings. Inside node.js we'll take care of assigning things to // their places. // We start the process this way in order to be more modular. Developers // who do not like how 'src/node.js' setups the module system but do like // Node's I/O bindings may want to replace 'f' with their own function. // Add a reference to the global object Local<Object> global = env->context()->Global();
The general process is as follows:
Load V8, OpenSSL...
Create an Environment
Set Process objects
Execute the node. js File
2. Looking at the global configuration process from the node. js file, let's talk about it. The node. js source code is too tricky. Is the C-language born style?
This file is about configuring global variables, configuring process, and defining module objects.
Later I will explain in depth the node. js file and the C ++ Class combined with src, and explain nodejs with the js Code under lib.
We can draw a conclusion: nodejs = node API + V8;
How can I learn from source code on github?
You cannot learn the source code by simply reading the source code. You must run the project and dynamically analyze its processing process during debugging to better understand the principle. Fortunately, the source code of node. js is very easy to compile and Debug. I will study its implementation mechanism through the following steps. First, I used Visual Studio 2010 for debugging in Windows 7. (Of course, it's okay if you want to use other environments.) Step 1: clone the source code from GitHub to a local environment (or directly download the compressed package) Step 2. Use the built-in vcbuild. bat script to generate the complete vs project solution file step 3, open the node generated in the previous step with Visual Studio 2010. the sln solution file sets the node as the main project, and then you can start compilation and debugging. There are many questions to explore, but they should also be focused on. In this process, you will find a new world. By learning the works of top developers, you can improve your skills faster. But obviously, your efforts and sweat are multiplied. I started to Access node. js a year and a half ago. At present, my most important project is basically based on it. Analyzing the implementation mechanism of node. js has greatly benefited me. However, looking back at my learning process, I did not consider learning from the bottom up from the implementation mechanism. Instead, I learned how to use various APIs from the top-down Perspective of "happy dummies" and read a little bit of code as appropriate. In this way, learning will be more directional, closely aligned with the needs, and easy to have a sense of accomplishment, easy to stick.
How does eclipse compile nodejs?
Compile nodejs with make, which has little to do with eclipse.
In fact, you can download the compiled installation package. On the official nodejs website, there are installation packages for several common environments.