diff options
author | bradnelson@google.com <bradnelson@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-19 02:46:32 +0000 |
---|---|---|
committer | bradnelson@google.com <bradnelson@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-19 02:46:32 +0000 |
commit | 745945afe8e9fbfad7bb9ed442143172bf690073 (patch) | |
tree | 770e9c5f61e1204221fb4c2887cb863ad8b6688f /native_client_sdk/src/project_templates | |
parent | f0953ccbeb01a7a4ed1daa3cb84c2bc42adbed1f (diff) | |
download | chromium_src-745945afe8e9fbfad7bb9ed442143172bf690073.zip chromium_src-745945afe8e9fbfad7bb9ed442143172bf690073.tar.gz chromium_src-745945afe8e9fbfad7bb9ed442143172bf690073.tar.bz2 |
Adding reduced version of sdk at 1387 to chrome tree.
BUG=None
TEST=None
R=noelallen@google.com
TBR
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110822 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk/src/project_templates')
13 files changed, 1536 insertions, 0 deletions
diff --git a/native_client_sdk/src/project_templates/README b/native_client_sdk/src/project_templates/README new file mode 100644 index 0000000..5aca398 --- /dev/null +++ b/native_client_sdk/src/project_templates/README @@ -0,0 +1,45 @@ +Welcome to the Native Client SDK project_templates directory. + +Currently, this directory contains a mechanism to allow a developer to +bootstrap a native client project and write a lot of the NaCl-specific code +automatically, so the developer can add her own functionality quickly. The +projects created are designed to be self-contained, meaning that they have +everything they need to run, except a server. + +To start a project, run "./init_project.py" or "python init_project.py" +depending on your system configuration. The script will give you usage +information when run with -h or when insufficient or malformed arguments are +provided. + +The result of the script is a project with the name you provide at a location +of your choice. If you have your own server, you may create the project in +a location it serves. Otherwise, you may create a project under the SDK +examples directory and examples/httpd.py to serve your project quickly - at +least temporarily. + +In the future, this directory is intended as a repository for useful stub code, +code snippets, and code generators that can be used to facilitate rapid +development. For now we support initial project setup via init_project.py, but +any generically useful code can be added here if it follows a reasonable +organization. The organization is as follows: + +project_templates: + Contains any top-level scripting elements that apply or may come in useful + for the generation of all NaCl/Pepper2 projects, common Makefile sections, + and this README. +project_templates/[language]: + For any given language there should be a directory with a name that is + commonly associated with that language. +project_templates/[topic] +project_templates/[language]/[topic] + For any given programming topic, such as audio, 2d, or 3d programming, there + should be a directory at the root level for any components that are not + language specific and that may apply to that topic. For corresponding + components that are language specific, a sub-directory for the topic may + also be created under the language directory. + +Note that the layout in this directory does not reflect the layout of the +projects that are created. It is merely a set of simple guidelines to help +organize generic code and utilities so they can be managed here. How +generated projects are laid out is left up to the design of the particular +code-generator. diff --git a/native_client_sdk/src/project_templates/c/build.scons b/native_client_sdk/src/project_templates/c/build.scons new file mode 100644 index 0000000..fcfcf0e --- /dev/null +++ b/native_client_sdk/src/project_templates/c/build.scons @@ -0,0 +1,15 @@ +#! -*- python -*- +# +# Copyright (c) 2011 The Native Client Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import make_nacl_env +import os + +nacl_env = make_nacl_env.NaClEnvironment( + nacl_platform=os.getenv('NACL_TARGET_PLATFORM')) + +sources = ['<PROJECT_NAME>.c'] + +nacl_env.AllNaClModules(sources, '<PROJECT_NAME>') diff --git a/native_client_sdk/src/project_templates/c/project_file.c b/native_client_sdk/src/project_templates/c/project_file.c new file mode 100644 index 0000000..7f25bd6 --- /dev/null +++ b/native_client_sdk/src/project_templates/c/project_file.c @@ -0,0 +1,227 @@ +/** @file <PROJECT_NAME>.c + * This example demonstrates loading, running and scripting a very simple + * NaCl module. + */ +#include <stdlib.h> +#include <string.h> +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/pp_module.h" +#include "ppapi/c/pp_var.h" +#include "ppapi/c/ppb.h" +#include "ppapi/c/ppb_instance.h" +#include "ppapi/c/ppb_messaging.h" +#include "ppapi/c/ppb_var.h" +#include "ppapi/c/ppp.h" +#include "ppapi/c/ppp_instance.h" +#include "ppapi/c/ppp_messaging.h" + +static PP_Module module_id = 0; +static struct PPB_Messaging* messaging_interface = NULL; +static struct PPB_Var* var_interface = NULL; + +/** + * Returns a mutable C string contained in the @a var or NULL if @a var is not + * string. This makes a copy of the string in the @a var and adds a NULL + * terminator. Note that VarToUtf8() does not guarantee the NULL terminator on + * the returned string. See the comments for VarToUtf8() in ppapi/c/ppb_var.h + * for more info. The caller is responsible for freeing the returned memory. + * @param[in] var PP_Var containing string. + * @return a mutable C string representation of @a var. + * @note The caller is responsible for freeing the returned string. + */ +/* TODO(sdk_user): 2. Uncomment this when you need it. It is commented out so + * that the compiler doesn't complain about unused functions. + */ +#if 0 +static char* AllocateCStrFromVar(struct PP_Var var) { + uint32_t len = 0; + if (var_interface != NULL) { + const char* var_c_str = var_interface->VarToUtf8(var, &len); + if (len > 0) { + char* c_str = (char*)malloc(len + 1); + memcpy(c_str, var_c_str, len); + c_str[len] = '\0'; + return c_str; + } + } + return NULL; +} +#endif + +/** + * Creates a new string PP_Var from C string. The resulting object will be a + * refcounted string object. It will be AddRef()ed for the caller. When the + * caller is done with it, it should be Release()d. + * @param[in] str C string to be converted to PP_Var + * @return PP_Var containing string. + */ +/* TODO(sdk_user): 3. Uncomment this when you need it. It is commented out so + * that the compiler doesn't complain about unused functions. + */ +#if 0 +static struct PP_Var AllocateVarFromCStr(const char* str) { + if (var_interface != NULL) + return var_interface->VarFromUtf8(module_id, str, strlen(str)); + return PP_MakeUndefined(); +} +#endif + +/** + * Called when the NaCl module is instantiated on the web page. The identifier + * of the new instance will be passed in as the first argument (this value is + * generated by the browser and is an opaque handle). This is called for each + * instantiation of the NaCl module, which is each time the <embed> tag for + * this module is encountered. + * + * If this function reports a failure (by returning @a PP_FALSE), the NaCl + * module will be deleted and DidDestroy will be called. + * @param[in] instance The identifier of the new instance representing this + * NaCl module. + * @param[in] argc The number of arguments contained in @a argn and @a argv. + * @param[in] argn An array of argument names. These argument names are + * supplied in the <embed> tag, for example: + * <embed id="nacl_module" dimensions="2"> + * will produce two arguments, one named "id" and one named "dimensions". + * @param[in] argv An array of argument values. These are the values of the + * arguments listed in the <embed> tag. In the above example, there will + * be two elements in this array, "nacl_module" and "2". The indices of + * these values match the indices of the corresponding names in @a argn. + * @return @a PP_TRUE on success. + */ +static PP_Bool Instance_DidCreate(PP_Instance instance, + uint32_t argc, + const char* argn[], + const char* argv[]) { + return PP_TRUE; +} + +/** + * Called when the NaCl module is destroyed. This will always be called, + * even if DidCreate returned failure. This routine should deallocate any data + * associated with the instance. + * @param[in] instance The identifier of the instance representing this NaCl + * module. + */ +static void Instance_DidDestroy(PP_Instance instance) { +} + +/** + * Called when the position, the size, or the clip rect of the element in the + * browser that corresponds to this NaCl module has changed. + * @param[in] instance The identifier of the instance representing this NaCl + * module. + * @param[in] position The location on the page of this NaCl module. This is + * relative to the top left corner of the viewport, which changes as the + * page is scrolled. + * @param[in] clip The visible region of the NaCl module. This is relative to + * the top left of the plugin's coordinate system (not the page). If the + * plugin is invisible, @a clip will be (0, 0, 0, 0). + */ +static void Instance_DidChangeView(PP_Instance instance, + const struct PP_Rect* position, + const struct PP_Rect* clip) { +} + +/** + * Notification that the given NaCl module has gained or lost focus. + * Having focus means that keyboard events will be sent to the NaCl module + * represented by @a instance. A NaCl module's default condition is that it + * will not have focus. + * + * Note: clicks on NaCl modules will give focus only if you handle the + * click event. You signal if you handled it by returning @a true from + * HandleInputEvent. Otherwise the browser will bubble the event and give + * focus to the element on the page that actually did end up consuming it. + * If you're not getting focus, check to make sure you're returning true from + * the mouse click in HandleInputEvent. + * @param[in] instance The identifier of the instance representing this NaCl + * module. + * @param[in] has_focus Indicates whether this NaCl module gained or lost + * event focus. + */ +static void Instance_DidChangeFocus(PP_Instance instance, + PP_Bool has_focus) { +} + +/** + * Handler that gets called after a full-frame module is instantiated based on + * registered MIME types. This function is not called on NaCl modules. This + * function is essentially a place-holder for the required function pointer in + * the PPP_Instance structure. + * @param[in] instance The identifier of the instance representing this NaCl + * module. + * @param[in] url_loader A PP_Resource an open PPB_URLLoader instance. + * @return PP_FALSE. + */ +static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance, + PP_Resource url_loader) { + /* NaCl modules do not need to handle the document load function. */ + return PP_FALSE; +} + + +/** + * Handler for messages coming in from the browser via postMessage. The + * @a var_message can contain anything: a JSON string; a string that encodes + * method names and arguments; etc. For example, you could use JSON.stringify + * in the browser to create a message that contains a method name and some + * parameters, something like this: + * var json_message = JSON.stringify({ "myMethod" : "3.14159" }); + * nacl_module.postMessage(json_message); + * On receipt of this message in @a var_message, you could parse the JSON to + * retrieve the method name, match it to a function call, and then call it with + * the parameter. + * @param[in] instance The instance ID. + * @param[in] message The contents, copied by value, of the message sent from + * browser via postMessage. + */ +void Messaging_HandleMessage(PP_Instance instance, struct PP_Var var_message) { + /* TODO(sdk_user): 1. Make this function handle the incoming message. */ +} + +/** + * Entry points for the module. + * Initialize instance interface and scriptable object class. + * @param[in] a_module_id Module ID + * @param[in] get_browser_interface Pointer to PPB_GetInterface + * @return PP_OK on success, any other value on failure. + */ +PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id, + PPB_GetInterface get_browser_interface) { + module_id = a_module_id; + var_interface = (struct PPB_Var*)(get_browser_interface(PPB_VAR_INTERFACE)); + messaging_interface = + (struct PPB_Messaging*)(get_browser_interface(PPB_MESSAGING_INTERFACE)); + return PP_OK; +} + +/** + * Returns an interface pointer for the interface of the given name, or NULL + * if the interface is not supported. + * @param[in] interface_name name of the interface + * @return pointer to the interface + */ +PP_EXPORT const void* PPP_GetInterface(const char* interface_name) { + if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) { + static struct PPP_Instance instance_interface = { + &Instance_DidCreate, + &Instance_DidDestroy, + &Instance_DidChangeView, + &Instance_DidChangeFocus, + &Instance_HandleDocumentLoad + }; + return &instance_interface; + } else if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) { + static struct PPP_Messaging messaging_interface = { + &Messaging_HandleMessage + }; + return &messaging_interface; + } + return NULL; +} + +/** + * Called before the plugin module is unloaded. + */ +PP_EXPORT void PPP_ShutdownModule() { +} diff --git a/native_client_sdk/src/project_templates/cc/build.scons b/native_client_sdk/src/project_templates/cc/build.scons new file mode 100644 index 0000000..537d17b --- /dev/null +++ b/native_client_sdk/src/project_templates/cc/build.scons @@ -0,0 +1,16 @@ +#! -*- python -*- +# +# Copyright (c) 2011 The Native Client Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import make_nacl_env +import nacl_utils +import os + +nacl_env = make_nacl_env.NaClEnvironment( + use_c_plus_plus_libs=True, nacl_platform=os.getenv('NACL_TARGET_PLATFORM')) + +sources = ['<PROJECT_NAME>.cc'] + +nacl_env.AllNaClModules(sources, '<PROJECT_NAME>') diff --git a/native_client_sdk/src/project_templates/cc/project_file.cc b/native_client_sdk/src/project_templates/cc/project_file.cc new file mode 100644 index 0000000..c0123fe --- /dev/null +++ b/native_client_sdk/src/project_templates/cc/project_file.cc @@ -0,0 +1,87 @@ +/// @file <PROJECT_NAME>.cc +/// This example demonstrates loading, running and scripting a very simple NaCl +/// module. To load the NaCl module, the browser first looks for the +/// CreateModule() factory method (at the end of this file). It calls +/// CreateModule() once to load the module code from your .nexe. After the +/// .nexe code is loaded, CreateModule() is not called again. +/// +/// Once the .nexe code is loaded, the browser than calls the CreateInstance() +/// method on the object returned by CreateModule(). It calls CreateInstance() +/// each time it encounters an <embed> tag that references your NaCl module. +/// +/// The browser can talk to your NaCl module via the postMessage() Javascript +/// function. When you call postMessage() on your NaCl module from the browser, +/// this becomes a call to the HandleMessage() method of your pp::Instance +/// subclass. You can send messages back to the browser by calling the +/// PostMessage() method on your pp::Instance. Note that these two methods +/// (postMessage() in Javascript and PostMessage() in C++) are asynchronous. +/// This means they return immediately - there is no waiting for the message +/// to be handled. This has implications in your program design, particularly +/// when mutating property values that are exposed to both the browser and the +/// NaCl module. + +#include <cstdio> +#include <string> +#include "ppapi/cpp/instance.h" +#include "ppapi/cpp/module.h" +#include "ppapi/cpp/var.h" + +/// The Instance class. One of these exists for each instance of your NaCl +/// module on the web page. The browser will ask the Module object to create +/// a new Instance for each occurence of the <embed> tag that has these +/// attributes: +/// type="application/x-nacl" +/// src="<PROJECT_NAME>.nmf" +/// To communicate with the browser, you must override HandleMessage() for +/// receiving messages from the borwser, and use PostMessage() to send messages +/// back to the browser. Note that this interface is entirely asynchronous. +class <ProjectName>Instance : public pp::Instance { + public: + /// The constructor creates the plugin-side instance. + /// @param[in] instance the handle to the browser-side plugin instance. + explicit <ProjectName>Instance(PP_Instance instance) : pp::Instance(instance) + {} + virtual ~<ProjectName>Instance() {} + + /// Handler for messages coming in from the browser via postMessage(). The + /// @a var_message can contain anything: a JSON string; a string that encodes + /// method names and arguments; etc. For example, you could use + /// JSON.stringify in the browser to create a message that contains a method + /// name and some parameters, something like this: + /// var json_message = JSON.stringify({ "myMethod" : "3.14159" }); + /// nacl_module.postMessage(json_message); + /// On receipt of this message in @a var_message, you could parse the JSON to + /// retrieve the method name, match it to a function call, and then call it + /// with the parameter. + /// @param[in] var_message The message posted by the browser. + virtual void HandleMessage(const pp::Var& var_message) { + // TODO(sdk_user): 1. Make this function handle the incoming message. + } +}; + +/// The Module class. The browser calls the CreateInstance() method to create +/// an instance of your NaCl module on the web page. The browser creates a new +/// instance for each <embed> tag with type="application/x-nacl". +class <ProjectName>Module : public pp::Module { + public: + <ProjectName>Module() : pp::Module() {} + virtual ~<ProjectName>Module() {} + + /// Create and return a <ProjectName>Instance object. + /// @param[in] instance The browser-side instance. + /// @return the plugin-side instance. + virtual pp::Instance* CreateInstance(PP_Instance instance) { + return new <ProjectName>Instance(instance); + } +}; + +namespace pp { +/// Factory function called by the browser when the module is first loaded. +/// The browser keeps a singleton of this module. It calls the +/// CreateInstance() method on the object you return to make instances. There +/// is one instance per <embed> tag on the page. This is the main binding +/// point for your NaCl module with the browser. +Module* CreateModule() { + return new <ProjectName>Module(); +} +} // namespace pp diff --git a/native_client_sdk/src/project_templates/html/project_file.html b/native_client_sdk/src/project_templates/html/project_file.html new file mode 100644 index 0000000..0b21ad9 --- /dev/null +++ b/native_client_sdk/src/project_templates/html/project_file.html @@ -0,0 +1,95 @@ +<!DOCTYPE html> +<html> +<head> + <title><ProjectName>!</title> + + <script type="text/javascript"> + <ProjectName>Module = null; // Global application object. + statusText = 'NO-STATUS'; + + // Indicate load success. + function moduleDidLoad() { + <ProjectName>Module = document.getElementById('<PROJECT_NAME>'); + updateStatus('SUCCESS'); + } + + // The 'message' event handler. This handler is fired when the NaCl module + // posts a message to the browser by calling PPB_Messaging.PostMessage() + // (in C) or pp::Instance.PostMessage() (in C++). This implementation + // simply displays the content of the message in an alert panel. + function handleMessage(message_event) { + alert(message_event.data); + } + + // If the page loads before the Native Client module loads, then set the + // status message indicating that the module is still loading. Otherwise, + // do not change the status message. + function pageDidLoad() { + if (<ProjectName>Module == null) { + updateStatus('LOADING...'); + } else { + // It's possible that the Native Client module onload event fired + // before the page's onload event. In this case, the status message + // will reflect 'SUCCESS', but won't be displayed. This call will + // display the current message. + updateStatus(); + } + } + + // Set the global status message. If the element with id 'statusField' + // exists, then set its HTML to the status message as well. + // opt_message The message test. If this is null or undefined, then + // attempt to set the element with id 'statusField' to the value of + // |statusText|. + function updateStatus(opt_message) { + if (opt_message) + statusText = opt_message; + var statusField = document.getElementById('status_field'); + if (statusField) { + statusField.innerHTML = statusText; + } + } + </script> +</head> +<body onload="pageDidLoad()"> + +<h1>Native Client Module <ProjectName></h1> +<p> + <!-- Load the published .nexe. This includes the 'nacl' attribute which + shows how to load multi-architecture modules. Each entry in the "nexes" + object in the .nmf manifest file is a key-value pair: the key is the + instruction set architecture ('x86-32', 'x86-64', etc.); the value is a URL + for the desired NaCl module. + To load the debug versions of your .nexes, set the 'nacl' attribute to the + _dbg.nmf version of the manifest file. + + Note: Since this NaCl module does not use any real-estate in the browser, + it's width and height are set to 0. + + Note: The <EMBED> element is wrapped inside a <DIV>, which has both a 'load' + and a 'message' event listener attached. This wrapping method is used + instead of attaching the event listeners directly to the <EMBED> element to + ensure that the listeners are active before the NaCl module 'load' event + fires. This also allows you to use PPB_Messaging.PostMessage() (in C) or + pp::Instance.PostMessage() (in C++) from within the initialization code in + your NaCl module. + --> + <div id="listener"> + <script type="text/javascript"> + var listener = document.getElementById('listener'); + listener.addEventListener('load', moduleDidLoad, true); + listener.addEventListener('message', handleMessage, true); + </script> + + <embed name="nacl_module" + id="<PROJECT_NAME>" + width=0 height=0 + src="<PROJECT_NAME>.nmf" + type="application/x-nacl" /> + </div> +</p> + +<h2>Status</h2> +<div id="status_field">NO-STATUS</div> +</body> +</html> diff --git a/native_client_sdk/src/project_templates/init_project.py b/native_client_sdk/src/project_templates/init_project.py new file mode 100755 index 0000000..4b5bad2 --- /dev/null +++ b/native_client_sdk/src/project_templates/init_project.py @@ -0,0 +1,502 @@ +#!/usr/bin/python2.6 +# +# Copyright (c) 2011 The Native Client Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""A simple project generator for Native Client projects written in C or C++. + +This script accepts a few argument which it uses as a description of a new NaCl +project. It sets up a project with a given name and a given primary language +(default: C++, optionally, C) using the appropriate files from this area. +This script does not handle setup for complex applications, just the basic +necessities to get a functional native client application stub. When this +script terminates a compileable project stub will exist with the specified +name, at the specified location. + +GetCamelCaseName(): Converts an underscore name to a camel case name. +GetCodeDirectory(): Decides what directory to pull source code from. +GetCodeSoureFiles(): Decides what source files to pull into the stub. +GetCommonSourceFiles(): Gives list of files needed by all project types. +GetHTMLDirectory(): Decides what directory to pull HTML stub from. +GetHTMLSourceFiles(): Gives HTML files to be included in project stub. +GetTargetFileName(): Converts a source file name into a project file name. +ParseArguments(): Parses the arguments provided by the user. +ReplaceInFile(): Replaces a given string with another in a given file. +ProjectInitializer: Maintains some state applicable to setting up a project. +main(): Executes the script. +""" + +__author__ = 'mlinck@google.com (Michael Linck)' + +import fileinput +import optparse +import os.path +import shutil +import sys +import uuid + +# A list of all platforms that should have make.cmd. +WINDOWS_BUILD_PLATFORMS = ['cygwin', 'win32'] + +# Tags that will be replaced in our the new project's source files. +PROJECT_NAME_TAG = '<PROJECT_NAME>' +PROJECT_NAME_CAMEL_CASE_TAG = '<ProjectName>' +SDK_ROOT_TAG = '<NACL_SDK_ROOT>' +NACL_PLATFORM_TAG = '<NACL_PLATFORM>' +VS_PROJECT_UUID_TAG = '<VS_PROJECT_UUID>' +VS_SOURCE_UUID_TAG = '<VS_SOURCE_UUID>' +VS_HEADER_UUID_TAG = '<VS_HEADER_UUID>' +VS_RESOURCE_UUID_TAG = '<VS_RESOURCE_UUID>' + +# This string is the part of the file name that will be replaced. +PROJECT_FILE_NAME = 'project_file' + +# Lists of source files that will be used for the new project. +COMMON_PROJECT_FILES = ['scons'] +C_SOURCE_FILES = ['build.scons', '%s.c' % PROJECT_FILE_NAME] +CC_SOURCE_FILES = ['build.scons', '%s.cc' % PROJECT_FILE_NAME] +HTML_FILES = ['%s.html' % PROJECT_FILE_NAME] +VS_FILES = ['%s.sln' % PROJECT_FILE_NAME, '%s.vcproj' % PROJECT_FILE_NAME] + +# Error needs to be a class, since we 'raise' it in several places. +class Error(Exception): + pass + + +def GetCamelCaseName(lower_case_name): + """Converts an underscore name to a camel case name. + + Args: + lower_case_name: The name in underscore-delimited lower case format. + + Returns: + The name in camel case format. + """ + camel_case_name = '' + name_parts = lower_case_name.split('_') + for part in name_parts: + if part: + camel_case_name += part.capitalize() + return camel_case_name + + +def GetCodeDirectory(is_c_project, project_templates_dir): + """Decides what directory to pull source code from. + + Args: + is_c_project: A boolean indicating whether this project is in C or not. + project_templates_dir: The path to the project_templates directory. + + Returns: + The code directory for the given project type. + """ + stub_directory = '' + if is_c_project: + stub_directory = os.path.join(project_templates_dir, 'c') + else: + stub_directory = os.path.join(project_templates_dir, 'cc') + return stub_directory + + +def GetCodeSourceFiles(is_c_project): + """Decides what source files to pull into the stub. + + Args: + is_c_project: A boolean indicating whether this project is in C or not. + + Returns: + The files that are specific to the requested type of project and live in its + directory. + """ + project_files = [] + if is_c_project: + project_files = C_SOURCE_FILES + else: + project_files = CC_SOURCE_FILES + return project_files + + +def GetCommonSourceFiles(): + """Gives list of files needed by all project types. + + Returns: + The files C and C++ projects have in common. These are the files that live + in the top level project_templates directory. + """ + project_files = COMMON_PROJECT_FILES + if sys.platform in WINDOWS_BUILD_PLATFORMS: + project_files.extend(['scons.bat']) + return project_files + + +def GetVsDirectory(project_templates_dir): + """Decides what directory to pull Visual Studio stub from. + + Args: + project_templates_dir: The path to the project_templates directory. + + Returns: + The directory where the HTML stub is to be found. + """ + return os.path.join(project_templates_dir, 'vs') + + +def GetVsProjectFiles(): + """Gives VisualStudio files to be included in project stub. + + Returns: + The VisualStudio files needed for the project. + """ + return VS_FILES + + +def GetHTMLDirectory(project_templates_dir): + """Decides what directory to pull HTML stub from. + + Args: + project_templates_dir: The path to the project_templates directory. + + Returns: + The directory where the HTML stub is to be found. + """ + return os.path.join(project_templates_dir, 'html') + + +def GetHTMLSourceFiles(): + """Gives HTML files to be included in project stub. + + Returns: + The HTML files needed for the project. + """ + return HTML_FILES + + +def GetTargetFileName(source_file_name, project_name): + """Converts a source file name into a project file name. + + Args: + source_file_name: The name of a file that is to be included in the project + stub, as it appears at the source location. + project_name: The name of the project that is being generated. + + Returns: + The target file name for a given source file. All project files are run + through this filter and it modifies them as needed. + """ + target_file_name = '' + if source_file_name.startswith(PROJECT_FILE_NAME): + target_file_name = source_file_name.replace(PROJECT_FILE_NAME, + project_name) + else: + target_file_name = source_file_name + return target_file_name + + +def GetDefaultProjectDir(): + """Determines the default project directory. + + The default directory root for new projects is called 'nacl_projects' under + the user's home directory. There are two ways to override this: you can set + the NACL_PROJECT_ROOT environment variable, or use the --directory option. + + Returns: + An os-specific path to the default project directory, which is called + 'nacl_projects' under the user's home directory. + """ + return os.getenv('NACL_PROJECT_ROOT', + os.path.join(os.path.expanduser('~'), 'nacl_projects')) + + +def ParseArguments(argv): + """Parses the arguments provided by the user. + + Parses the command line options and makes sure the script errors when it is + supposed to. + + Args: + argv: The argument array. + + Returns: + The options structure that represents the arguments after they have been + parsed. + """ + parser = optparse.OptionParser() + parser.add_option( + '-n', '--name', dest='project_name', + default='', + help=('Required: the name of the new project to be stubbed out.\n' + 'Please use lower case names with underscore, i.e. hello_world.')) + parser.add_option( + '-d', '--directory', dest='project_directory', + default=GetDefaultProjectDir(), + help=('Optional: If set, the new project will be created under this ' + 'directory and the directory created if necessary.')) + parser.add_option( + '-c', action='store_true', dest='is_c_project', + default=False, + help=('Optional: If set, this will generate a C project. Default ' + 'is C++.')) + parser.add_option( + '-p', '--nacl-platform', dest='nacl_platform', + default='pepper_17', + help=('Optional: if set, the new project will target the given nacl\n' + 'platform. Default is the most current platform. e.g. pepper_17')) + parser.add_option( + '--vsproj', action='store_true', dest='is_vs_project', + default=False, + help=('Optional: If set, generate Visual Studio project files.')) + result = parser.parse_args(argv) + options = result[0] + args = result[1] + #options, args) = parser.parse_args(argv) + if args: + parser.print_help() + sys.exit(1) + elif not options.project_name.islower(): + print('--name missing or in incorrect format. Please use -h for ' + 'instructions.') + sys.exit(1) + return options + + +class ProjectInitializer(object): + """Maintains the state of the project that is being created.""" + + def __init__(self, is_c_project, is_vs_project, project_name, + project_location, nacl_platform, project_templates_dir, + os_resource=os): + """Initializes all the fields that are known after parsing the parameters. + + Args: + is_c_project: A boolean indicating whether this project is in C or not. + is_vs_project: A boolean indicating whether this project has Visual + Studio support. + project_name: A string containing the name of the project to be created. + project_location: A path indicating where the new project is to be placed. + project_templates_dir: The path to the project_templates directory. + os_resource: A resource to be used as os. Provided for unit testing. + """ + self.__is_c_project = is_c_project + self.__is_vs_project = is_vs_project + self.__project_files = [] + self.__project_name = project_name + self.__project_location = project_location + self.__nacl_platform = nacl_platform + self.__project_templates_dir = project_templates_dir + # System resources are properties so mocks can be inserted. + self.__fileinput = fileinput + self.__os = os_resource + self.__shutil = shutil + self.__sys = sys + self.__CreateProjectDirectory() + + def CopyAndRenameFiles(self, source_dir, file_names): + """Places files in the new project's directory and renames them as needed. + + Copies the given files from the given source directory into the new + project's directory, renaming them as necessary. Each file that is created + in the project directory is also added to self.__project_files. + + Args: + source_dir: A path indicating where the files are to be copied from. + file_names: The list of files that is to be copied out of source_dir. + """ + for source_file_name in file_names: + target_file_name = GetTargetFileName(source_file_name, + self.__project_name) + copy_source_file = self.os.path.join(source_dir, source_file_name) + copy_target_file = self.os.path.join(self.__project_dir, target_file_name) + self.shutil.copy(copy_source_file, copy_target_file) + self.__project_files += [copy_target_file] + + def __CreateProjectDirectory(self): + """Creates the project's directory and any parents as necessary.""" + self.__project_dir = self.os.path.join(self.__project_location, + self.__project_name) + if self.os.path.exists(self.__project_dir): + raise Error("Error: directory '%s' already exists" % self.__project_dir) + self.os.makedirs(self.__project_dir) + + def PrepareDirectoryContent(self): + """Prepares the directory for the new project. + + This function's job is to know what directories need to be used and what + files need to be copied and renamed. It uses several tiny helper functions + to do this. + There are three locations from which files are copied to create a project. + That number may change in the future. + """ + code_source_dir = GetCodeDirectory(self.__is_c_project, + self.__project_templates_dir) + code_source_files = GetCodeSourceFiles(self.__is_c_project) + html_source_dir = GetHTMLDirectory(self.__project_templates_dir) + html_source_files = GetHTMLSourceFiles() + common_source_files = GetCommonSourceFiles() + self.CopyAndRenameFiles(code_source_dir, code_source_files) + self.CopyAndRenameFiles(html_source_dir, html_source_files) + self.CopyAndRenameFiles(self.__project_templates_dir, + common_source_files) + if self.__is_vs_project: + vs_source_dir = GetVsDirectory(self.__project_templates_dir) + vs_files = GetVsProjectFiles() + self.CopyAndRenameFiles(vs_source_dir, vs_files) + print('init_project has copied the appropriate files to: %s' % + self.__project_dir) + + def PrepareFileContent(self): + """Changes contents of files in the new project as needed. + + Goes through each file in the project that is being created and replaces + contents as necessary. + """ + camel_case_name = GetCamelCaseName(self.__project_name) + sdk_root_dir = os.getenv('NACL_SDK_ROOT', None) + if not sdk_root_dir: + raise Error("Error: NACL_SDK_ROOT is not set") + sdk_root_dir = self.os.path.abspath(sdk_root_dir) + if self.__is_vs_project: + project_uuid = str(uuid.uuid4()).upper() + vs_source_uuid = str(uuid.uuid4()).upper() + vs_header_uuid = str(uuid.uuid4()).upper() + vs_resource_uuid = str(uuid.uuid4()).upper() + for project_file in self.__project_files: + self.ReplaceInFile(project_file, PROJECT_NAME_TAG, self.__project_name) + self.ReplaceInFile(project_file, + PROJECT_NAME_CAMEL_CASE_TAG, + camel_case_name) + self.ReplaceInFile(project_file, SDK_ROOT_TAG, sdk_root_dir) + self.ReplaceInFile(project_file, NACL_PLATFORM_TAG, self.__nacl_platform) + if self.__is_vs_project: + self.ReplaceInFile(project_file, VS_PROJECT_UUID_TAG, project_uuid) + self.ReplaceInFile(project_file, VS_SOURCE_UUID_TAG, vs_source_uuid) + self.ReplaceInFile(project_file, VS_HEADER_UUID_TAG, vs_header_uuid) + self.ReplaceInFile(project_file, VS_RESOURCE_UUID_TAG, vs_resource_uuid) + + def ReplaceInFile(self, file_path, old_text, new_text): + """Replaces a given string with another in a given file. + + Args: + file_path: The path to the file that is to be modified. + old_text: The text that is to be removed. + new_text: The text that is to be added in place of old_text. + """ + for line in self.fileinput.input(file_path, inplace=1, mode='U'): + self.sys.stdout.write(line.replace(old_text, new_text)) + + # The following properties exist to make unit testing possible. + + def _GetFileinput(self): + """Accessor for Fileinput property.""" + return self.__fileinput + + def __GetFileinput(self): + """Indirect Accessor for _GetFileinput.""" + return self._GetFileinput() + + def _SetFileinput(self, fileinput_resource): + """Accessor for Fileinput property.""" + self.__fileinput = fileinput_resource + + def __SetFileinput(self, fileinput_resource): + """Indirect Accessor for _SetFileinput.""" + return self._SetFileinput(fileinput_resource) + + fileinput = property( + __GetFileinput, __SetFileinput, + doc="""Gets and sets the resource to use as fileinput.""") + + def _GetOS(self): + """Accessor for os property.""" + return self.__os + + def __GetOS(self): + """Indirect Accessor for _GetOS.""" + return self._GetOS() + + def _SetOS(self, os_resource): + """Accessor for os property.""" + self.__os = os_resource + + def __SetOS(self, os_resource): + """Indirect Accessor for _SetOS.""" + return self._SetOS(os_resource) + + os = property(__GetOS, __SetOS, + doc="""Gets and sets the resource to use as os.""") + + def _GetShutil(self): + """Accessor for shutil property.""" + return self.__shutil + + def __GetShutil(self): + """Indirect Accessor for _GetShutil.""" + return self._GetShutil() + + def _SetShutil(self, shutil_resource): + """Accessor for shutil property.""" + self.__shutil = shutil_resource + + def __SetShutil(self, shutil_resource): + """Indirect Accessor for _SetShutil.""" + return self._SetShutil(shutil_resource) + + shutil = property(__GetShutil, __SetShutil, + doc="""Gets and sets the resource to use as shutil.""") + + def _GetSys(self): + """Accessor for sys property.""" + return self.__sys + + def __GetSys(self): + """Indirect Accessor for _GetSys.""" + return self._GetSys() + + def _SetSys(self, sys_resource): + """Accessor for sys property.""" + self.__sys = sys_resource + + def __SetSys(self, sys_resource): + """Indirect Accessor for _SetSys.""" + return self._SetSys(sys_resource) + + sys = property(__GetSys, __SetSys, + doc="""Gets and sets the resource to use as sys.""") + + +def main(argv): + """Prepares the new project. + + Args: + argv: The arguments passed to the script by the shell. + """ + print 'init_project parsing its arguments.' + script_dir = os.path.abspath(os.path.dirname(__file__)) + options = ParseArguments(argv) + print 'init_project is preparing your project.' + # Check to see if the project is going into the SDK bundle. If so, issue a + # warning. + sdk_root_dir = os.getenv('NACL_SDK_ROOT', None) + if sdk_root_dir: + if os.path.normpath(options.project_directory).count( + os.path.normpath(sdk_root_dir)) > 0: + print('WARNING: It looks like you are creating projects in the NaCl SDK ' + 'directory %s.\nThese might be removed at the next update.' % + sdk_root_dir) + project_initializer = ProjectInitializer(options.is_c_project, + options.is_vs_project, + options.project_name, + options.project_directory, + options.nacl_platform, + script_dir) + project_initializer.PrepareDirectoryContent() + project_initializer.PrepareFileContent() + return 0 + + +if __name__ == '__main__': + try: + sys.exit(main(sys.argv[1:])) + except Exception as error: + print error + sys.exit(1) diff --git a/native_client_sdk/src/project_templates/init_project_test.py b/native_client_sdk/src/project_templates/init_project_test.py new file mode 100755 index 0000000..681916f --- /dev/null +++ b/native_client_sdk/src/project_templates/init_project_test.py @@ -0,0 +1,256 @@ +#!/usr/bin/python2.6 +# +# Copyright (c) 2011 The Native Client Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Unit tests for init_project.py.""" + +__author__ = 'mlinck@google.com (Michael Linck)' + +import fileinput +import os +import shutil +import sys +import unittest +import mox +import init_project + + +def TestMock(file_path, open_func): + temp_file = open_func(file_path) + temp_file.close() + + +class TestGlobalFunctions(unittest.TestCase): + """Class for test cases to cover globally declared helper functions.""" + + def testGetCamelCaseName(self): + output = init_project.GetCamelCaseName('camel_case_name') + self.assertEqual(output, 'CamelCaseName') + output = init_project.GetCamelCaseName('print_42') + self.assertEqual(output, 'Print42') + + def testGetCodeDirectory(self): + output = init_project.GetCodeDirectory(True, '') + self.assertEqual(output, 'c') + output = init_project.GetCodeDirectory(False, '') + self.assertEqual(output, 'cc') + output = init_project.GetCodeDirectory(True, 'test') + self.assertEqual(output, 'test/c') + output = init_project.GetCodeDirectory(False, 'test') + self.assertEqual(output, 'test/cc') + + def testGetCodeSourceFiles(self): + output = init_project.GetCodeSourceFiles(False) + self.assertEqual(output, init_project.CC_SOURCE_FILES) + output = init_project.GetCodeSourceFiles(True) + self.assertEqual(output, init_project.C_SOURCE_FILES) + + def testGetCommonSourceFiles(self): + output = init_project.GetCommonSourceFiles() + expected_output_linux = init_project.COMMON_PROJECT_FILES + expected_output_windows = init_project.COMMON_PROJECT_FILES + expected_output_windows.extend(['scons.bat']) + linux_match = (output == expected_output_linux) + windows_match = (output == expected_output_windows) + passed = (linux_match | windows_match) + self.assertTrue(passed) + + def testGetHTMLDirectory(self): + output = init_project.GetHTMLDirectory('') + self.assertEqual(output, 'html') + output = init_project.GetHTMLDirectory('test') + self.assertEqual(output, 'test/html') + + def testGetHTMLSourceFiles(self): + output = init_project.GetHTMLSourceFiles() + self.assertEqual(output, init_project.HTML_FILES) + + def testGetTargetFileName(self): + output = init_project.GetTargetFileName('project_file.cc', 'bonkers') + self.assertEqual(output, 'bonkers.cc') + output = init_project.GetTargetFileName('constant.html', 'bonkers') + self.assertEqual(output, 'constant.html') + + def testParseArguments(self): + output = init_project.ParseArguments(['-n', 'test_name', '-d', 'test/dir']) + self.assertEqual(output.is_c_project, False) + self.assertEqual(output.project_name, 'test_name') + self.assertEqual(output.project_directory, 'test/dir') + output = init_project.ParseArguments(['-n', 'test_name_2', '-c']) + self.assertEqual(output.is_c_project, True) + self.assertEqual(output.project_name, 'test_name_2') + self.assertEqual(output.project_directory, + init_project.GetDefaultProjectDir()) + + +class TestProjectInitializer(unittest.TestCase): + """Class for test cases to cover public interface of ProjectInitializer.""" + + def setUp(self): + self.script_dir = os.path.abspath(os.path.dirname(__file__)) + self.nacl_src_dir = os.getenv('NACL_SDK_ROOT', None) + self.mock_factory = mox.Mox() + # This mock is only valid for initialization and will be overwritten + # after ward by self.os_mock. + init_path_mock = self.mock_factory.CreateMock(os.path) + init_path_mock.join('test/dir', 'test_project').AndReturn( + 'test/dir/test_project') + init_path_mock.exists('test/dir/test_project').AndReturn(False) + init_os_mock = self.mock_factory.CreateMock(os) + init_os_mock.path = init_path_mock + init_os_mock.makedirs('test/dir/test_project') + self.mock_factory.ReplayAll() + self.test_subject = init_project.ProjectInitializer( + # True => is C project, False => is vs project + True, False, 'test_project', 'test/dir', 'pepper_14', self.script_dir, + init_os_mock) + self.mock_factory.VerifyAll() + self.InitializeResourceMocks() + + def InitializeResourceMocks(self): + """Can be called multiple times if multiple functions need to be tested.""" + self.fileinput_mock = self.mock_factory.CreateMock(fileinput) + self.test_subject.fileinput = self.fileinput_mock + self.os_mock = self.mock_factory.CreateMock(os) + self.test_subject.os = self.os_mock + self.shutil_mock = self.mock_factory.CreateMock(shutil) + self.test_subject.shutil = self.shutil_mock + self.sys_mock = self.mock_factory.CreateMock(sys) + self.test_subject.sys = self.sys_mock + + def testCopyAndRenameFiles(self): + self.shutil_mock.copy('source/dir/normal_name.txt', + 'test/dir/test_project/normal_name.txt') + self.shutil_mock.copy('source/dir/project_file.txt', + 'test/dir/test_project/test_project.txt') + self.os_mock.path = os.path + self.mock_factory.ReplayAll() + self.test_subject.CopyAndRenameFiles( + 'source/dir', ['normal_name.txt', 'project_file.txt']) + self.mock_factory.VerifyAll() + + def testPrepareDirectoryContent(self): + self.shutil_mock.copy( + '%s/c/build.scons' % self.script_dir, + 'test/dir/test_project/build.scons') + self.shutil_mock.copy( + '%s/c/project_file.c' % self.script_dir, + 'test/dir/test_project/test_project.c') + self.shutil_mock.copy( + '%s/html/project_file.html' % self.script_dir, + 'test/dir/test_project/test_project.html') + self.shutil_mock.copy( + '%s/scons' % self.script_dir, + 'test/dir/test_project/scons') + self.shutil_mock.copy( + '%s/scons.bat' % self.script_dir, + 'test/dir/test_project/scons.bat') + self.os_mock.path = os.path + self.mock_factory.ReplayAll() + self.test_subject.PrepareDirectoryContent() + self.mock_factory.VerifyAll() + + def testPrepareFileContent(self): + self.testCopyAndRenameFiles() + # We need a new set of resource mocks since the old ones have already been + # used. + self.InitializeResourceMocks() + path_mock = self.mock_factory.CreateMock(os.path) + stdout_mock = self.mock_factory.CreateMock(sys.stdout) + self.os_mock.path = path_mock + path_mock.abspath(self.nacl_src_dir).AndReturn(self.nacl_src_dir) + self.fileinput_mock.input( + 'test/dir/test_project/normal_name.txt', + inplace=1, mode='U').AndReturn( + ['A line with <PROJECT_NAME>.', + 'A line with <ProjectName>.', + 'A line with <NACL_SDK_ROOT>.', + 'A line with <NACL_PLATFORM>.']) + stdout_mock.write('A line with test_project.') + stdout_mock.write('A line with <ProjectName>.') + stdout_mock.write('A line with <NACL_SDK_ROOT>.') + stdout_mock.write('A line with <NACL_PLATFORM>.') + self.fileinput_mock.input( + 'test/dir/test_project/normal_name.txt', + inplace=1, mode='U').AndReturn( + ['A line with test_project.', + 'A line with <ProjectName>.', + 'A line with <NACL_SDK_ROOT>.', + 'A line with <NACL_PLATFORM>.']) + stdout_mock.write('A line with test_project.') + stdout_mock.write('A line with TestProject.') + stdout_mock.write('A line with <NACL_SDK_ROOT>.') + stdout_mock.write('A line with <NACL_PLATFORM>.') + self.fileinput_mock.input( + 'test/dir/test_project/normal_name.txt', + inplace=1, mode='U').AndReturn( + ['A line with test_project.', + 'A line with TestProject.', + 'A line with <NACL_SDK_ROOT>.', + 'A line with <NACL_PLATFORM>.']) + stdout_mock.write('A line with test_project.') + stdout_mock.write('A line with TestProject.') + stdout_mock.write('A line with %s.' % self.nacl_src_dir) + stdout_mock.write('A line with <NACL_PLATFORM>.') + self.fileinput_mock.input( + 'test/dir/test_project/normal_name.txt', + inplace=1, mode='U').AndReturn( + ['A line with test_project.', + 'A line with TestProject.', + 'A line with some/dir.', + 'A line with <NACL_PLATFORM>.']) + stdout_mock.write('A line with test_project.') + stdout_mock.write('A line with TestProject.') + stdout_mock.write('A line with some/dir.') + stdout_mock.write('A line with pepper_14.') + # One multi-line file with different replacements has already been mocked + # so we make this next test simpler. + self.fileinput_mock.input( + 'test/dir/test_project/test_project.txt', + inplace=1, mode='U').AndReturn(['A line with no replaceable text.']) + stdout_mock.write('A line with no replaceable text.') + self.fileinput_mock.input( + 'test/dir/test_project/test_project.txt', + inplace=1, mode='U').AndReturn(['A line with no replaceable text.']) + stdout_mock.write('A line with no replaceable text.') + self.fileinput_mock.input( + 'test/dir/test_project/test_project.txt', + inplace=1, mode='U').AndReturn(['A line with no replaceable text.']) + stdout_mock.write('A line with no replaceable text.') + self.fileinput_mock.input( + 'test/dir/test_project/test_project.txt', + inplace=1, mode='U').AndReturn(['A line with no replaceable text.']) + stdout_mock.write('A line with no replaceable text.') + self.sys_mock.stdout = stdout_mock + self.mock_factory.ReplayAll() + self.test_subject.PrepareFileContent() + self.mock_factory.VerifyAll() + + def testReplaceInFile(self): + self.fileinput_mock.input('test/path', inplace=1, mode='U').AndReturn( + ['A sentence replace_me.']) + stdout_mock = self.mock_factory.CreateMock(sys.stdout) + stdout_mock.write('A sentence with_this.') + self.sys_mock.stdout = stdout_mock + self.mock_factory.ReplayAll() + self.test_subject.ReplaceInFile('test/path', 'replace_me', 'with_this') + self.mock_factory.VerifyAll() + + +def RunTests(): + # It's possible to do this with one suite instead of two, but then it's + # harder to read the test output. + return_value = 1 + suite_one = unittest.TestLoader().loadTestsFromTestCase(TestGlobalFunctions) + result_one = unittest.TextTestRunner(verbosity=2).run(suite_one) + suite_two = unittest.TestLoader().loadTestsFromTestCase( + TestProjectInitializer) + result_two = unittest.TextTestRunner(verbosity=2).run(suite_two) + if result_one.wasSuccessful() and result_two.wasSuccessful(): + return_value = 0 + return return_value + +if __name__ == '__main__': + sys.exit(RunTests()) diff --git a/native_client_sdk/src/project_templates/scons b/native_client_sdk/src/project_templates/scons new file mode 100755 index 0000000..2b7e0d3 --- /dev/null +++ b/native_client_sdk/src/project_templates/scons @@ -0,0 +1,32 @@ +#!/bin/bash +# +# Copyright (c) 2011 The Native Client Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + + +readonly SCRIPT_DIR="$(dirname "$0")" +readonly SCRIPT_DIR_ABS="$(cd "${SCRIPT_DIR}" ; pwd -P)" + +export NACL_SDK_ROOT=<NACL_SDK_ROOT> +# NACL_TARGET_PLATFORM is really the name of a folder with the base dir - +# usually NACL_SDK_ROOT - within which the toolchain for the target platform +# are found. +# Replace the platform with the name of your target platform. For example, to +# build applications that target the pepper_17 API, set +# NACL_TARGET_PLATFORM="pepper_17" +export NACL_TARGET_PLATFORM="<NACL_PLATFORM>" + +readonly NACL_PLATFORM_DIR="${NACL_SDK_ROOT}/${NACL_TARGET_PLATFORM}" +readonly BASE_SCRIPT="${NACL_PLATFORM_DIR}/third_party/scons-2.0.1/script/scons" + +export SCONS_LIB_DIR="${NACL_PLATFORM_DIR}/third_party/scons-2.0.1/engine" +export PYTHONPATH="${NACL_PLATFORM_DIR}/third_party/scons-2.0.1/engine" +# We have to do this because scons overrides PYTHONPATH and does not preserve +# what is provided by the OS. The custom variable name won't be overwritten. +export PYMOX="${NACL_PLATFORM_DIR}/third_party/pymox" + +"${BASE_SCRIPT}" --file=build.scons \ + --site-dir="${NACL_PLATFORM_DIR}/build_tools/nacl_sdk_scons" \ + $* + diff --git a/native_client_sdk/src/project_templates/scons.bat b/native_client_sdk/src/project_templates/scons.bat new file mode 100755 index 0000000..f487e28 --- /dev/null +++ b/native_client_sdk/src/project_templates/scons.bat @@ -0,0 +1,31 @@ +@echo off + +:: Copyright (c) 2011 The Native Client Authors. All rights reserved. +:: Use of this source code is governed by a BSD-style license that can be +:: found in the LICENSE file. + +setlocal + +set NACL_SDK_ROOT=<NACL_SDK_ROOT> +:: NACL_TARGET_PLATFORM is really the name of a folder with the base dir - +:: usually NACL_SDK_ROOT - within which the toolchain for the target platform +:: are found. +:: Replace the platform with the name of your target platform. For example, to +:: build applications that target the pepper_17 API, set +:: NACL_TARGET_PLATFORM=pepper_17 +set NACL_TARGET_PLATFORM=<NACL_PLATFORM> + +set NACL_PLATFORM_DIR=%NACL_SDK_ROOT%\%NACL_TARGET_PLATFORM% + +:: Set the PYTHONPATH and SCONS_LIB_DIR so we can import SCons modules +set SCONS_LIB_DIR=%NACL_PLATFORM_DIR%\third_party\scons-2.0.1\engine +set PYTHONPATH=%NACL_PLATFORM_DIR%\third_party\scons-2.0.1\engine + +:: We have to do this because scons overrides PYTHONPATH and does not preserve +:: what is provided by the OS. The custom variable name won't be overwritten. +set PYMOX=%NACL_PLATFORM_DIR%\third_party\pymox + +:: Run the included copy of scons. +python -O -OO "%NACL_PLATFORM_DIR%\third_party\scons-2.0.1\script\scons" ^ +--file=build.scons ^ +--site-dir="%NACL_PLATFORM_DIR%\build_tools\nacl_sdk_scons" %* diff --git a/native_client_sdk/src/project_templates/test.scons b/native_client_sdk/src/project_templates/test.scons new file mode 100644 index 0000000..c00e2a8 --- /dev/null +++ b/native_client_sdk/src/project_templates/test.scons @@ -0,0 +1,26 @@ +#! -*- python -*- +# +# Copyright (c) 2010 The Native Client Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Build file for tests of init_project interface. + +Adapted from scons documentation: http://www.scons.org/wiki/UnitTests + +RunUnitTests(): Runs a comment and uses the return code to determine success. +""" + +__author__ = 'mlinck@google.com (Michael Linck)' + +import os +import sys + +Import('env') + +#TODO(mlinck) Enable this test again when it works on Windows +cmd = env.CreatePythonUnitTest(filename='init_project_test.py', + dependencies=['init_project.py'], + disabled=env['IS_WINDOWS']) + +env.AddNodeToTestSuite(cmd, ['bot'], 'run_init_project_test', 'small') diff --git a/native_client_sdk/src/project_templates/vs/project_file.sln b/native_client_sdk/src/project_templates/vs/project_file.sln new file mode 100644 index 0000000..05f5169 --- /dev/null +++ b/native_client_sdk/src/project_templates/vs/project_file.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "<PROJECT_NAME>", "<PROJECT_NAME>.vcproj", "{<VS_PROJECT_UUID>}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {<VS_PROJECT_UUID>}.Debug|Win32.ActiveCfg = Debug|Win32 + {<VS_PROJECT_UUID>}.Debug|Win32.Build.0 = Debug|Win32 + {<VS_PROJECT_UUID>}.Release|Win32.ActiveCfg = Release|Win32 + {<VS_PROJECT_UUID>}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/native_client_sdk/src/project_templates/vs/project_file.vcproj b/native_client_sdk/src/project_templates/vs/project_file.vcproj new file mode 100644 index 0000000..d2b0f25 --- /dev/null +++ b/native_client_sdk/src/project_templates/vs/project_file.vcproj @@ -0,0 +1,184 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9.00" + Name="<PROJECT_NAME>" + ProjectGUID="{<VS_PROJECT_UUID>" + RootNamespace="<PROJECT_NAME>" + Keyword="MakeFileProj" + TargetFrameworkVersion="196613" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="0" + > + <Tool + Name="VCNMakeTool" + BuildCommandLine="$(NACL_SDK_ROOT)\<NACL_PLATFORM>\examples\scons" + ReBuildCommandLine="$(NACL_SDK_ROOT)\<NACL_PLATFORM>\examples\scons -c && $(NACL_SDK_ROOT)\<NACL_PLATFORM>\examples\scons" + CleanCommandLine="$(NACL_SDK_ROOT)\<NACL_PLATFORM>\examples\scons -c" + Output="<PROJECT_NAME>_x86_64_dbg.nexe" + PreprocessorDefinitions="WIN32;_DEBUG" + IncludeSearchPath="" + ForcedIncludes="" + AssemblySearchPath="" + ForcedUsingAssemblies="" + CompileAsManaged="" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="0" + > + <Tool + Name="VCNMakeTool" + BuildCommandLine="" + ReBuildCommandLine="" + CleanCommandLine="" + Output="<PROJECT_NAME>.exe" + PreprocessorDefinitions="WIN32;NDEBUG" + IncludeSearchPath="" + ForcedIncludes="" + AssemblySearchPath="" + ForcedUsingAssemblies="" + CompileAsManaged="" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{<VS_SOURCE_UUID>}" + > + <File + RelativePath=".\build.scons" + > + </File> + <File + RelativePath=".\<PROJECT_NAME>.cc" + > + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{<VS_HEADER_UUID>}" + > + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" + UniqueIdentifier="{<VS_RESOURCE_UUID>}" + > + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9.00" + Name="<PROJECT_NAME>" + ProjectGUID="{<VS_PROJECT_UUID>" + RootNamespace="<PROJECT_NAME>" + Keyword="MakeFileProj" + TargetFrameworkVersion="196613" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="0" + > + <Tool + Name="VCNMakeTool" + BuildCommandLine="$(NACL_SDK_ROOT)\<NACL_PLATFORM>\examples\scons" + ReBuildCommandLine="$(NACL_SDK_ROOT)\<NACL_PLATFORM>\examples\scons -c && $(NACL_SDK_ROOT)\<NACL_PLATFORM>\examples\scons" + CleanCommandLine="$(NACL_SDK_ROOT)\<NACL_PLATFORM>\examples\scons -c" + Output="<PROJECT_NAME>_x86_64_dbg.nexe" + PreprocessorDefinitions="WIN32;_DEBUG" + IncludeSearchPath="" + ForcedIncludes="" + AssemblySearchPath="" + ForcedUsingAssemblies="" + CompileAsManaged="" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="0" + > + <Tool + Name="VCNMakeTool" + BuildCommandLine="" + ReBuildCommandLine="" + CleanCommandLine="" + Output="<PROJECT_NAME>.exe" + PreprocessorDefinitions="WIN32;NDEBUG" + IncludeSearchPath="" + ForcedIncludes="" + AssemblySearchPath="" + ForcedUsingAssemblies="" + CompileAsManaged="" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{<VS_SOURCE_UUID>}" + > + <File + RelativePath=".\build.scons" + > + </File> + <File + RelativePath=".\<PROJECT_NAME>.cc" + > + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{<VS_HEADER_UUID>}" + > + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" + UniqueIdentifier="{<VS_RESOURCE_UUID>}" + > + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> |