📜 ⬆️ ⬇️

C ++ Development for BlackBerry 10 without using IDE (using OpenGL ES 2)

Under BlackBerry OS 10 there is an excellent development environment: QNX Momentics IDE, based on Eclipse. And everything would be fine, but when it comes to automating the build of builds, setting up build configurations on TeamCity, the IDE needs a fifth leg like a dog. That was the biggest problem when porting our BlackBerry engine . Let's figure out how to build a project, package a distribution, sign it, and run it on an emulator — all without using an IDE.



Dependencies


')
To build the project we need:



C ++ project



Let's start with the fact that we outline the raw of our minimalist application that will draw a color triangle using OpenGL ES 2.

This will be main.cpp.
#include <assert.h> #include <screen/screen.h> #include <bps/navigator.h> #include <bps/screen.h> #include <bps/bps.h> #include <bps/event.h> #include <bps/locale.h> #include <bps/virtualkeyboard.h> #include <sys/keycodes.h> #include <input/event_types.h> #include <input/screen_helpers.h> #include <stdarg.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <EGL/egl.h> #include <GLES2/gl2.h> #include "bbutil.h" static const char g_vShaderStr[] = "#version 100\n" "precision highp float;\n" "attribute vec3 vPosition;\n" "attribute vec3 vColor;\n" "varying vec4 Color;\n" "void main()\n" "{\n" " Color = vec4( vColor, 1.0 );\n" " gl_Position = vec4( vPosition, 1.0 );\n" "}\n"; static const char g_fShaderStr[] = "#version 100\n" "precision highp float;\n" "varying vec4 Color;\n" "void main()\n" "{\n" " gl_FragColor = Color;\n" "}\n"; static GLuint g_ProgramObject = 0; static GLuint LoadShader( GLenum type, const char* shaderSrc ) { GLuint shader = glCreateShader( type ); glShaderSource ( shader, 1, &shaderSrc, NULL ); glCompileShader ( shader ); GLint compiled; glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled ); GLsizei MaxLength = 0; glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &MaxLength ); char* InfoLog = new char[MaxLength]; glGetShaderInfoLog( shader, MaxLength, &MaxLength, InfoLog ); return shader; } static void GLDebug_LoadStaticProgramObject() { if ( g_ProgramObject == 0 ) { GLuint vertexShader = LoadShader ( GL_VERTEX_SHADER, g_vShaderStr ); GLuint fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, g_fShaderStr ); g_ProgramObject = glCreateProgram ( ); glAttachShader ( g_ProgramObject, vertexShader ); glAttachShader ( g_ProgramObject, fragmentShader ); glLinkProgram ( g_ProgramObject ); GLint linked; glGetProgramiv ( g_ProgramObject, GL_LINK_STATUS, &linked ); GLsizei Length = 0; GLsizei MaxLength = 0; glGetProgramiv( g_ProgramObject, GL_INFO_LOG_LENGTH, &MaxLength ); char* InfoLog = new char[MaxLength]; glGetProgramInfoLog( g_ProgramObject, MaxLength, &Length, InfoLog ); } } static void GLDebug_RenderTriangle() { const GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f }; const GLfloat vColors[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; glUseProgram ( g_ProgramObject ); GLint Loc1 = glGetAttribLocation( g_ProgramObject, "vPosition" ); GLint Loc2 = glGetAttribLocation( g_ProgramObject, "vColor" ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); glVertexAttribPointer ( Loc1, 3, GL_FLOAT, GL_FALSE, 0, vVertices ); glVertexAttribPointer ( Loc2, 3, GL_FLOAT, GL_FALSE, 0, vColors ); glEnableVertexAttribArray ( Loc1 ); glEnableVertexAttribArray ( Loc2 ); //glUseProgram ( g_ProgramObject ); glDisable( GL_DEPTH_TEST ); glDrawArrays ( GL_TRIANGLES, 0, 3 ); glUseProgram ( 0 ); glDisableVertexAttribArray ( Loc1 ); glDisableVertexAttribArray ( Loc2 ); } static screen_context_t screen_cxt; void handleScreenEvent( bps_event_t* event ) { screen_event_t screen_event = screen_event_get_event( event ); // handle clicks, touches, keypresses } void handleNavigatorEvent( bps_event_t* event ) { int rc; bps_event_t* activation_event = NULL; switch ( bps_event_get_code( event ) ) { case NAVIGATOR_ORIENTATION_CHECK: // signal navigator that we do not intend to resize navigator_orientation_check_response( event, false ); break; } } int main( int argc, char* argv[] ) { int rc; int exit_application = 0; screen_create_context( &screen_cxt, 0 ); bps_initialize(); //Use utility code to initialize EGL for rendering with GL ES 2.0 if ( EXIT_SUCCESS != bbutil_init_egl( screen_cxt ) ) { fprintf( stderr, "bbutil_init_egl failed\n" ); bbutil_terminate(); screen_destroy_context( screen_cxt ); return 0; } // Signal BPS library that navigator and screen events will be requested if ( BPS_SUCCESS != screen_request_events( screen_cxt ) ) { fprintf( stderr, "screen_request_events failed\n" ); bbutil_terminate(); screen_destroy_context( screen_cxt ); bps_shutdown(); return 0; } if ( BPS_SUCCESS != navigator_request_events( 0 ) ) { fprintf( stderr, "navigator_request_events failed\n" ); bbutil_terminate(); screen_destroy_context( screen_cxt ); bps_shutdown(); return 0; } if ( BPS_SUCCESS != virtualkeyboard_request_events( 0 ) ) { fprintf( stderr, "virtualkeyboard_request_events failed\n" ); bbutil_terminate(); screen_destroy_context( screen_cxt ); bps_shutdown(); return 0; } // Signal BPS library that navigator orientation is not to be locked if ( BPS_SUCCESS != navigator_rotation_lock( false ) ) { fprintf( stderr, "navigator_rotation_lock failed\n" ); bbutil_terminate(); screen_destroy_context( screen_cxt ); bps_shutdown(); return 0; } // Query width and height of the window surface created by utility code EGLint surface_width, surface_height; eglQuerySurface( egl_disp, egl_surf, EGL_WIDTH, &surface_width ); eglQuerySurface( egl_disp, egl_surf, EGL_HEIGHT, &surface_height ); GLDebug_LoadStaticProgramObject(); while ( !exit_application ) { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Request and process all available BPS events bps_event_t* event = NULL; for ( ;; ) { rc = bps_get_event( &event, 0 ); assert( rc == BPS_SUCCESS ); if ( event ) { int domain = bps_event_get_domain( event ); if ( domain == screen_get_domain() ) { handleScreenEvent( event ); } else if ( domain == navigator_get_domain() ) { handleNavigatorEvent( event ); if ( NAVIGATOR_EXIT == bps_event_get_code( event ) ) { exit_application = 1; } } } else break; } // render frame here GLDebug_RenderTriangle(); bbutil_swap(); } // Stop requesting events from libscreen screen_stop_events( screen_cxt ); // Shut down BPS library for this process bps_shutdown(); // Use utility code to terminate EGL setup bbutil_terminate(); // Destroy libscreen context screen_destroy_context( screen_cxt ); return 0; } 



We’ll also need bbutil.c and bbutil.h from the BlackBerry 10 Native SDK examples. In order not to engage in the search for treasures, here is their slightly neutered content (but absolutely enough to launch our mini-example).

bbutil.h
 /* * Copyright (c) 2011-2012 Research In Motion Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _UTILITY_H_INCLUDED #define _UTILITY_H_INCLUDED #include <EGL/egl.h> #include <screen/screen.h> #include <sys/platform.h> #define USING_GL20 extern EGLDisplay egl_disp; extern EGLSurface egl_surf; typedef struct font_t font_t; #define BBUTIL_DEFAULT_FONT "/usr/fonts/font_repository/monotype/arial.ttf" #ifdef __cplusplus extern "C" { #endif /** * Initializes EGL * * @param libscreen context that will be used for EGL setup * @return EXIT_SUCCESS if initialization succeeded otherwise EXIT_FAILURE */ int bbutil_init_egl( screen_context_t ctx ); /** * Terminates EGL */ void bbutil_terminate(); /** * Swaps default bbutil window surface to the screen */ void bbutil_swap(); /** * Returns dpi for a given screen * * @param ctx path libscreen context that corresponds to display of interest * @return dpi for a given screen */ int bbutil_calculate_dpi( screen_context_t ctx ); /** * Rotates the screen to a given angle * * @param angle to rotate screen surface to, must by 0, 90, 180, or 270 * @return EXIT_SUCCESS if texture loading succeeded otherwise EXIT_FAILURE */ int bbutil_rotate_screen_surface( int angle ); #ifdef __cplusplus } #endif #endif 



bbutil.c
 /* * Copyright (c) 2011-2012 Research In Motion Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <assert.h> #include <ctype.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/keycodes.h> #include <time.h> #include <stdbool.h> #include <math.h> #include "bbutil.h" #ifdef USING_GL11 #include <GLES/gl.h> #include <GLES/glext.h> #elif defined(USING_GL20) #include <GLES2/gl2.h> #else #error bbutil must be compiled with either USING_GL11 or USING_GL20 flags #endif EGLDisplay egl_disp; EGLSurface egl_surf; static EGLConfig egl_conf; static EGLContext egl_ctx; static screen_context_t screen_ctx; static screen_window_t screen_win; static screen_display_t screen_disp; static int nbuffers = 2; static int initialized = 0; #ifdef USING_GL20 static GLuint text_rendering_program; static int text_program_initialized = 0; static GLint positionLoc; static GLint texcoordLoc; static GLint textureLoc; static GLint colorLoc; #endif struct font_t { unsigned int font_texture; float pt; float advance[128]; float width[128]; float height[128]; float tex_x1[128]; float tex_x2[128]; float tex_y1[128]; float tex_y2[128]; float offset_x[128]; float offset_y[128]; int initialized; }; static void bbutil_egl_perror( const char* msg ) { static const char* errmsg[] = { "function succeeded", "EGL is not initialized, or could not be initialized, for the specified display", "cannot access a requested resource", "failed to allocate resources for the requested operation", "an unrecognized attribute or attribute value was passed in an attribute list", "an EGLConfig argument does not name a valid EGLConfig", "an EGLContext argument does not name a valid EGLContext", "the current surface of the calling thread is no longer valid", "an EGLDisplay argument does not name a valid EGLDisplay", "arguments are inconsistent", "an EGLNativePixmapType argument does not refer to a valid native pixmap", "an EGLNativeWindowType argument does not refer to a valid native window", "one or more argument values are invalid", "an EGLSurface argument does not name a valid surface configured for rendering", "a power management event has occurred", "unknown error code" }; int message_index = eglGetError() - EGL_SUCCESS; if ( message_index < 0 || message_index > 14 ) { message_index = 15; } fprintf( stderr, "%s: %s\n", msg, errmsg[message_index] ); } int bbutil_init_egl( screen_context_t ctx ) { int usage; int format = SCREEN_FORMAT_RGBX8888; EGLint interval = 1; int rc, num_configs; EGLint attrib_list[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, 0, EGL_NONE }; #ifdef USING_GL11 usage = SCREEN_USAGE_OPENGL_ES1 | SCREEN_USAGE_ROTATION; attrib_list[9] = EGL_OPENGL_ES_BIT; #elif defined(USING_GL20) usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_ROTATION; attrib_list[9] = EGL_OPENGL_ES2_BIT; EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; #else fprintf( stderr, "bbutil should be compiled with either USING_GL11 or USING_GL20 -D flags\n" ); return EXIT_FAILURE; #endif //Simple egl initialization screen_ctx = ctx; egl_disp = eglGetDisplay( EGL_DEFAULT_DISPLAY ); if ( egl_disp == EGL_NO_DISPLAY ) { bbutil_egl_perror( "eglGetDisplay" ); bbutil_terminate(); return EXIT_FAILURE; } rc = eglInitialize( egl_disp, NULL, NULL ); if ( rc != EGL_TRUE ) { bbutil_egl_perror( "eglInitialize" ); bbutil_terminate(); return EXIT_FAILURE; } rc = eglBindAPI( EGL_OPENGL_ES_API ); if ( rc != EGL_TRUE ) { bbutil_egl_perror( "eglBindApi" ); bbutil_terminate(); return EXIT_FAILURE; } if ( !eglChooseConfig( egl_disp, attrib_list, &egl_conf, 1, &num_configs ) ) { bbutil_terminate(); return EXIT_FAILURE; } #ifdef USING_GL20 egl_ctx = eglCreateContext( egl_disp, egl_conf, EGL_NO_CONTEXT, attributes ); #elif defined(USING_GL11) egl_ctx = eglCreateContext( egl_disp, egl_conf, EGL_NO_CONTEXT, NULL ); #endif if ( egl_ctx == EGL_NO_CONTEXT ) { bbutil_egl_perror( "eglCreateContext" ); bbutil_terminate(); return EXIT_FAILURE; } rc = screen_create_window( &screen_win, screen_ctx ); if ( rc ) { perror( "screen_create_window" ); bbutil_terminate(); return EXIT_FAILURE; } rc = screen_set_window_property_iv( screen_win, SCREEN_PROPERTY_FORMAT, &format ); if ( rc ) { perror( "screen_set_window_property_iv(SCREEN_PROPERTY_FORMAT)" ); bbutil_terminate(); return EXIT_FAILURE; } rc = screen_set_window_property_iv( screen_win, SCREEN_PROPERTY_USAGE, &usage ); if ( rc ) { perror( "screen_set_window_property_iv(SCREEN_PROPERTY_USAGE)" ); bbutil_terminate(); return EXIT_FAILURE; } rc = screen_get_window_property_pv( screen_win, SCREEN_PROPERTY_DISPLAY, ( void** )&screen_disp ); if ( rc ) { perror( "screen_get_window_property_pv" ); bbutil_terminate(); return EXIT_FAILURE; } int screen_resolution[2]; rc = screen_get_display_property_iv( screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution ); if ( rc ) { perror( "screen_get_display_property_iv" ); bbutil_terminate(); return EXIT_FAILURE; } int angle = atoi( getenv( "ORIENTATION" ) ); screen_display_mode_t screen_mode; rc = screen_get_display_property_pv( screen_disp, SCREEN_PROPERTY_MODE, ( void** )&screen_mode ); if ( rc ) { perror( "screen_get_display_property_pv" ); bbutil_terminate(); return EXIT_FAILURE; } int size[2]; rc = screen_get_window_property_iv( screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size ); if ( rc ) { perror( "screen_get_window_property_iv" ); bbutil_terminate(); return EXIT_FAILURE; } int buffer_size[2] = {size[0], size[1]}; if ( ( angle == 0 ) || ( angle == 180 ) ) { if ( ( ( screen_mode.width > screen_mode.height ) && ( size[0] < size[1] ) ) || ( ( screen_mode.width < screen_mode.height ) && ( size[0] > size[1] ) ) ) { buffer_size[1] = size[0]; buffer_size[0] = size[1]; } } else if ( ( angle == 90 ) || ( angle == 270 ) ) { if ( ( ( screen_mode.width > screen_mode.height ) && ( size[0] > size[1] ) ) || ( ( screen_mode.width < screen_mode.height && size[0] < size[1] ) ) ) { buffer_size[1] = size[0]; buffer_size[0] = size[1]; } } else { fprintf( stderr, "Navigator returned an unexpected orientation angle.\n" ); bbutil_terminate(); return EXIT_FAILURE; } rc = screen_set_window_property_iv( screen_win, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size ); if ( rc ) { perror( "screen_set_window_property_iv" ); bbutil_terminate(); return EXIT_FAILURE; } rc = screen_set_window_property_iv( screen_win, SCREEN_PROPERTY_ROTATION, &angle ); if ( rc ) { perror( "screen_set_window_property_iv" ); bbutil_terminate(); return EXIT_FAILURE; } rc = screen_create_window_buffers( screen_win, nbuffers ); if ( rc ) { perror( "screen_create_window_buffers" ); bbutil_terminate(); return EXIT_FAILURE; } egl_surf = eglCreateWindowSurface( egl_disp, egl_conf, screen_win, NULL ); if ( egl_surf == EGL_NO_SURFACE ) { bbutil_egl_perror( "eglCreateWindowSurface" ); bbutil_terminate(); return EXIT_FAILURE; } rc = eglMakeCurrent( egl_disp, egl_surf, egl_surf, egl_ctx ); if ( rc != EGL_TRUE ) { bbutil_egl_perror( "eglMakeCurrent" ); bbutil_terminate(); return EXIT_FAILURE; } rc = eglSwapInterval( egl_disp, interval ); if ( rc != EGL_TRUE ) { bbutil_egl_perror( "eglSwapInterval" ); bbutil_terminate(); return EXIT_FAILURE; } initialized = 1; return EXIT_SUCCESS; } void bbutil_terminate() { //Typical EGL cleanup if ( egl_disp != EGL_NO_DISPLAY ) { eglMakeCurrent( egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); if ( egl_surf != EGL_NO_SURFACE ) { eglDestroySurface( egl_disp, egl_surf ); egl_surf = EGL_NO_SURFACE; } if ( egl_ctx != EGL_NO_CONTEXT ) { eglDestroyContext( egl_disp, egl_ctx ); egl_ctx = EGL_NO_CONTEXT; } if ( screen_win != NULL ) { screen_destroy_window( screen_win ); screen_win = NULL; } eglTerminate( egl_disp ); egl_disp = EGL_NO_DISPLAY; } eglReleaseThread(); initialized = 0; } void bbutil_swap() { int rc = eglSwapBuffers( egl_disp, egl_surf ); if ( rc != EGL_TRUE ) { bbutil_egl_perror( "eglSwapBuffers" ); } } /* Finds the next power of 2 */ static inline int nextp2( int x ) { int val = 1; while ( val < x ) { val <<= 1; } return val; } int bbutil_calculate_dpi( screen_context_t ctx ) { int rc; int screen_phys_size[2]; rc = screen_get_display_property_iv( screen_disp, SCREEN_PROPERTY_PHYSICAL_SIZE, screen_phys_size ); if ( rc ) { perror( "screen_get_display_property_iv" ); bbutil_terminate(); return EXIT_FAILURE; } //Simulator will return 0,0 for physical size of the screen, so use 170 as default dpi if ( ( screen_phys_size[0] == 0 ) && ( screen_phys_size[1] == 0 ) ) { return 170; } else { int screen_resolution[2]; rc = screen_get_display_property_iv( screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution ); if ( rc ) { perror( "screen_get_display_property_iv" ); bbutil_terminate(); return EXIT_FAILURE; } double diagonal_pixels = sqrt( screen_resolution[0] * screen_resolution[0] + screen_resolution[1] * screen_resolution[1] ); double diagonal_inches = 0.0393700787 * sqrt( screen_phys_size[0] * screen_phys_size[0] + screen_phys_size[1] * screen_phys_size[1] ); return ( int )( diagonal_pixels / diagonal_inches + 0.5 ); } } int bbutil_rotate_screen_surface( int angle ) { int rc, rotation, skip = 1, temp;; EGLint interval = 1; int size[2]; if ( ( angle != 0 ) && ( angle != 90 ) && ( angle != 180 ) && ( angle != 270 ) ) { fprintf( stderr, "Invalid angle\n" ); return EXIT_FAILURE; } rc = screen_get_window_property_iv( screen_win, SCREEN_PROPERTY_ROTATION, &rotation ); if ( rc ) { perror( "screen_set_window_property_iv" ); return EXIT_FAILURE; } rc = screen_get_window_property_iv( screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size ); if ( rc ) { perror( "screen_set_window_property_iv" ); return EXIT_FAILURE; } switch ( angle - rotation ) { case -270: case -90: case 90: case 270: temp = size[0]; size[0] = size[1]; size[1] = temp; skip = 0; break; } if ( !skip ) { rc = eglMakeCurrent( egl_disp, NULL, NULL, NULL ); if ( rc != EGL_TRUE ) { bbutil_egl_perror( "eglMakeCurrent" ); return EXIT_FAILURE; } rc = eglDestroySurface( egl_disp, egl_surf ); if ( rc != EGL_TRUE ) { bbutil_egl_perror( "eglMakeCurrent" ); return EXIT_FAILURE; } rc = screen_set_window_property_iv( screen_win, SCREEN_PROPERTY_SOURCE_SIZE, size ); if ( rc ) { perror( "screen_set_window_property_iv" ); return EXIT_FAILURE; } rc = screen_set_window_property_iv( screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size ); if ( rc ) { perror( "screen_set_window_property_iv" ); return EXIT_FAILURE; } egl_surf = eglCreateWindowSurface( egl_disp, egl_conf, screen_win, NULL ); if ( egl_surf == EGL_NO_SURFACE ) { bbutil_egl_perror( "eglCreateWindowSurface" ); return EXIT_FAILURE; } rc = eglMakeCurrent( egl_disp, egl_surf, egl_surf, egl_ctx ); if ( rc != EGL_TRUE ) { bbutil_egl_perror( "eglMakeCurrent" ); return EXIT_FAILURE; } rc = eglSwapInterval( egl_disp, interval ); if ( rc != EGL_TRUE ) { bbutil_egl_perror( "eglSwapInterval" ); return EXIT_FAILURE; } } rc = screen_set_window_property_iv( screen_win, SCREEN_PROPERTY_ROTATION, &angle ); if ( rc ) { perror( "screen_set_window_property_iv" ); return EXIT_FAILURE; } return EXIT_SUCCESS; } 



Build project



Inside the BlackBerry 10 is QNX and the build for it is done using gcc. Write the makefile :

 BBARCH=x86 CC = i486-pc-nto-qnx8.0.0-gcc.exe CXX = i486-pc-nto-qnx8.0.0-gcc.exe AR = i486-pc-nto-qnx8.0.0-ar.exe OBJDIR=out OUTDIR=out OBJS = $(OBJDIR)/main.o $(OBJDIR)/bbutil.o $(OBJDIR)/bbutil.o: bbutil.c bbutil.h $(CC) -c bbutil.c -o $(OBJDIR)/bbutil.o $(CFLAGS) $(OBJDIR)/main.o: main.cpp $(CXX) -c main.cpp -o $(OBJDIR)/main.o $(CFLAGS) $(CPPFLAGS) OBJS += $(OBJDIR)/bbutil.o $(OBJDIR)/main.o USEDLIBS = -lstdc++ -lbps -lscreen -lm -lEGL -lGLESv2 -lfreetype -lsocket -lcurl -lOpenAL CFLAGS = -m32 -fomit-frame-pointer CPPFLAGS = -std=gnu++0x -fpermissive PACK: $(OBJS) rm -f $(OBJDIR)/pack.a ar -ru $(OBJDIR)/pack.a $(OBJS) all: $(OBJS) PACK $(CXX) $(CFLAGS) $(CPPFLAGS) -o Main.exe-$(BBARCH) main.cpp $(OBJDIR)/pack.a $(USEDLIBS) 


Do not forget to create a folder out for temporary files.

Now the project’s binary can almost be built with the make all command, you just need to add the environment variables needed for the BlackBerry 10 Native SDK. Since there are several possible targets (device on arm and emulator on x86), we decided to create a simple python script that will launch the build. Here is make-x86.py :

 #!/usr/bin/python import os Target = "M:/BBNDK/target_10_0_9_1673/qnx6" Host = "M:/BBNDK/host_10_0_9_404/win32/x86" os.environ['QNX_TARGET'] = Target os.environ['QNX_HOST' ] = Host os.environ['PATH' ] = Host + "/usr/bin;" + os.environ['PATH'] os.system( "make all" ) 


Run make-x86.py and get the Main.exe-x86 binary.

Build Package



Now you need to create a package that is suitable for installation on BlackBerry 10. Write the description of the package in bar-descriptor-x86.xml

 <?xml version="1.0" encoding="utf-8" standalone="no"?> <qnx xmlns="http://www.qnx.com/schemas/application/1.0"> <id>com.linderdaum.test_app</id> <name>Test App</name> <versionNumber>1.0.0</versionNumber> <buildId>1</buildId> <description>Test App</description> <author>Linderdaum</author> <platformVersion>10.0.9.1673</platformVersion> <initialWindow> <systemChrome>none</systemChrome> <transparent>false</transparent> <aspectRatio>landscape</aspectRatio> <autoOrients>false</autoOrients> </initialWindow> <category>core.games</category> <asset path="BB10Res/icon.png">icon.png</asset> <configuration id="com.qnx.qcc.toolChain.1246487324" name="Simulator-Debug"> <platformArchitecture>x86</platformArchitecture> <asset path="Main.exe-x86" entry="true" type="Qnx/Elf">Main.exe-x86</asset> </configuration> <icon> <image>icon.png</image> </icon> <permission system="true">run_native</permission> <env var="LD_LIBRARY_PATH" value="app/native/lib"/> </qnx> 


and do not forget to put the appropriate icon in BB10Res / icon.png . I have this 150x150:
image

We pack everything into Main-x86.bar:

 blackberry-nativepackager -devMode -package Main-x86.bar bar-descriptor-x86.xml 


Install and Run



It remains only to install on the emulator:

 blackberry-deploy -installApp -device 192.168.70.130 Main-x86.bar 


image

And run:

image

PS In order to download the app to the BlackBerry App World , you need to sign it. From the command line, this is done with one command:

 blackberry-signer -storepass <   > Main-armv7.bar 


PPS Sorry, that so much code. But you can save and paste it all and in 15 minutes run the finished application.

Source: https://habr.com/ru/post/165523/


All Articles