Generated DLL for emulator | developer.brewmp.com Generated DLL for emulator | developer.brewmp.com

Developer

Generated DLL for emulator

Is there another way to generate BREW emulator (DLL) builds besides using VC++? If so, where can I find more info?

Thanks.

I've been doing it with gcc under Cygwin for a while. If you're not used to a UN*X environment you may have a big learning curve ahead of you. I'll just give a couple of pointers (and encouragement :D) here, assuming you've got some familiarity with GNU make and gcc.
Overall, the process is almost identical to using arm-elf-gcc for device builds. That topic is already widely covered in this forum, so I suggest just reading every post.
You need to install Cygwin from cygwin.com. You may need to add some packages that aren't selected by default, but the installer is smart about remembering what you already have so if you forget something you can go back to the same link later and just add what you need. For starters, make sure you get gcc and make from the Devel section.
You don't need to get and build arm-elf-gcc unless you also want to be building for devices. arm-elf-gcc doesn't come with Cygwin: see Qualcomm's GCC Support For BREW stuff.
Here's a snippet of the Makefile I use to build .dlls for the emulator:
BREW_OBJECTS = AEEModGen.o AEEAppGen.o GCCResolver.o
GNUDLL_CC = /usr/bin/gcc
GNUDLL_CPP = $(GNUDLL_CC)
GNUDLL_TPP = $(GNUDLL_CC)
GNUDLL_LINK = /usr/bin/ld
ifeq ($(COMPILATION_MODE),gnudll)
# form of GNU compiler targeting BREW emulator
# NOTE: BREWelf2mod needs symbols, and presubably strips them, so link doesn't
CC = $(GNUDLL_CC)
CPP = $(GNUDLL_CPP)
TPP = $(GNUDLL_TPP)
LINK = $(GNUDLL_LINK)
CFLAGS = -c -O3 -Os \
-Wall -I$(BREWSDKINC) \
-fno-rtti -fno-exceptions -fshort-enums -fno-builtin \
-DPHONE_$(PHONE) -DVER=\"$(VER)\"" \
-DAEE_SIMULATOR -D__int64=long\ long
LFLAGS = -s -shared -static -nostdlib
LFLAGS_POST =
EXE = dll
MOD =
OBJDIR = gdd/$(PHONE)
endif
# universal compile steps:
$(BREW_OBJECTS:%=$(OBJDIR)/%): $(OBJDIR)/%.o: $(BREW_HEADERS)
$(BREW_OBJECTS:%=$(OBJDIR)/%): $(OBJDIR)/%.o: $(BREWSDKSRC)/%.c
@echo $< ""---->"" $@
@mkdir -p $(OBJDIR)
@$(CC) $(CFLAGS) $< -o $@
$(OBJDIR)/%.o: %.cpp $(HEADERS)
@echo $< ""---->"" $@
@mkdir -p $(OBJDIR)
@$(TPP) $(CFLAGS) $< -o $@
# universal link step:
$(OBJDIR)/$(PROJ).$(EXE): $(OBJECTS:%=$(OBJDIR)/%)
@echo linking $@
@mkdir -p $(OBJDIR)
@$(LINK) $(LFLAGS) -o $@ $^ $(LFLAGS_POST)
The TPP and COMPILATION_MODE stuff is because I use the same rules for building with arm-elf-gcc and armcc, but I'm leaving that out since it's a bit off topic. If I had a Makefile that *only* made .dll it would be a lot easier to understand, but I don't have time right now to generate one that I'm sure is free of mistakes.
The critical flags to use are -DAEE_SIMULATOR for $(CFLAGS) and -shared for $(LFLAGS). You may also need to twiddle the BREW SDK headers as described elsewhere in this forum for using arm-elf-gcc. The -D__int64=long\ long is to work around Microsoft's *nonstandard* syntax for 64 bit integers.
Anyhow, for this to be useful you'll probably *really* need to know make. But at least I can attest that it is possible and cheaper than using MSVC++.
-Jesse"

I've been doing it with gcc under Cygwin for a while. If you're not used to a UN*X environment you may have a big learning curve ahead of you. I'll just give a couple of pointers (and encouragement :D) here, assuming you've got some familiarity with GNU make and gcc.
Overall, the process is almost identical to using arm-elf-gcc for device builds. That topic is already widely covered in this forum, so I suggest just reading every post.
You need to install Cygwin from cygwin.com. You may need to add some packages that aren't selected by default, but the installer is smart about remembering what you already have so if you forget something you can go back to the same link later and just add what you need. For starters, make sure you get gcc and make from the Devel section.
You don't need to get and build arm-elf-gcc unless you also want to be building for devices. arm-elf-gcc doesn't come with Cygwin: see Qualcomm's GCC Support For BREW stuff.
Here's a snippet of the Makefile I use to build .dlls for the emulator:
BREW_OBJECTS = AEEModGen.o AEEAppGen.o GCCResolver.o
GNUDLL_CC = /usr/bin/gcc
GNUDLL_CPP = $(GNUDLL_CC)
GNUDLL_TPP = $(GNUDLL_CC)
GNUDLL_LINK = /usr/bin/ld
ifeq ($(COMPILATION_MODE),gnudll)
# form of GNU compiler targeting BREW emulator
# NOTE: BREWelf2mod needs symbols, and presubably strips them, so link doesn't
CC = $(GNUDLL_CC)
CPP = $(GNUDLL_CPP)
TPP = $(GNUDLL_TPP)
LINK = $(GNUDLL_LINK)
CFLAGS = -c -O3 -Os \
-Wall -I$(BREWSDKINC) \
-fno-rtti -fno-exceptions -fshort-enums -fno-builtin \
-DPHONE_$(PHONE) -DVER=\"$(VER)\"" \
-DAEE_SIMULATOR -D__int64=long\ long
LFLAGS = -s -shared -static -nostdlib
LFLAGS_POST =
EXE = dll
MOD =
OBJDIR = gdd/$(PHONE)
endif
# universal compile steps:
$(BREW_OBJECTS:%=$(OBJDIR)/%): $(OBJDIR)/%.o: $(BREW_HEADERS)
$(BREW_OBJECTS:%=$(OBJDIR)/%): $(OBJDIR)/%.o: $(BREWSDKSRC)/%.c
@echo $< ""---->"" $@
@mkdir -p $(OBJDIR)
@$(CC) $(CFLAGS) $< -o $@
$(OBJDIR)/%.o: %.cpp $(HEADERS)
@echo $< ""---->"" $@
@mkdir -p $(OBJDIR)
@$(TPP) $(CFLAGS) $< -o $@
# universal link step:
$(OBJDIR)/$(PROJ).$(EXE): $(OBJECTS:%=$(OBJDIR)/%)
@echo linking $@
@mkdir -p $(OBJDIR)
@$(LINK) $(LFLAGS) -o $@ $^ $(LFLAGS_POST)
The TPP and COMPILATION_MODE stuff is because I use the same rules for building with arm-elf-gcc and armcc, but I'm leaving that out since it's a bit off topic. If I had a Makefile that *only* made .dll it would be a lot easier to understand, but I don't have time right now to generate one that I'm sure is free of mistakes.
The critical flags to use are -DAEE_SIMULATOR for $(CFLAGS) and -shared for $(LFLAGS). You may also need to twiddle the BREW SDK headers as described elsewhere in this forum for using arm-elf-gcc. The -D__int64=long\ long is to work around Microsoft's *nonstandard* syntax for 64 bit integers.
Anyhow, for this to be useful you'll probably *really* need to know make. But at least I can attest that it is possible and cheaper than using MSVC++.
-Jesse"

For those of you (like me) not as familiar with makefiles, but who have got Tyndal's example from http://brewforums.qualcomm.com/showthread.php?s=&threadid=1601 working I edited gccMakefile and the buildme batch file to generate DLLs. You can put the attached dllMakefile in your GNUDE home directory (c:\gnude) and the dllme file in the same directory as your source. You may need to edit variable names in both these files to get them to point to both your GNUDE and GCC home directories.
I just commented out the lines I changed, so if you already have gccMakefile up and running you can compare and contrast the differences in dllMakefile. I'm really new to this, so please share any improvements or issues.

For those of you (like me) not as familiar with makefiles, but who have got Tyndal's example from http://brewforums.qualcomm.com/showthread.php?s=&threadid=1601 working I edited gccMakefile and the buildme batch file to generate DLLs. You can put the attached dllMakefile in your GNUDE home directory (c:\gnude) and the dllme file in the same directory as your source. You may need to edit variable names in both these files to get them to point to both your GNUDE and GCC home directories.
I just commented out the lines I changed, so if you already have gccMakefile up and running you can compare and contrast the differences in dllMakefile. I'm really new to this, so please share any improvements or issues.

http://sourceforge.net/projects/dev-cpp
You can build DLLs to the emulator using DevCPP. It has a nice IDE, syntax highlighting, code completion, etc... Unfortunately, I didn't use it for a long time, and I wasn't able to debug my code, but well..the DLL's were built and ran without problems! :)

http://sourceforge.net/projects/dev-cpp
You can build DLLs to the emulator using DevCPP. It has a nice IDE, syntax highlighting, code completion, etc... Unfortunately, I didn't use it for a long time, and I wasn't able to debug my code, but well..the DLL's were built and ran without problems! :)

Hi, all.
I'm getting a linker error "-shared and -static cannot be used together", is this a new restriction with later releases of ld? I've got Cygwin 3.4.4 (latest release) installed, and I noticed this thread dates back to 2003. I'm using a slightly modified version of the dllMakefile that's posted in this thread, updated only to build my sources. The link flags are the same:
LINK_CMD = -s -shared -static -nostdlib -o
Anyone ever get this error? Seems like if I don't have both flags, the linker wants to include stdlib in my build....
Thanks!
Sam

Hi, all.
I'm getting a linker error "-shared and -static cannot be used together", is this a new restriction with later releases of ld? I've got Cygwin 3.4.4 (latest release) installed, and I noticed this thread dates back to 2003. I'm using a slightly modified version of the dllMakefile that's posted in this thread, updated only to build my sources. The link flags are the same:
LINK_CMD = -s -shared -static -nostdlib -o
Anyone ever get this error? Seems like if I don't have both flags, the linker wants to include stdlib in my build....
Thanks!
Sam

-shared means you're trying to generate a .dll (or a .so, if you were targetting a unix, which you're not).
-static means you're trying to generate a .exe.
For BREW work, you definitely want -shared (and only -shared). The link problem can be fixed with -nostdlib.
Oh, wait. You have -nostdlib. Maybe you also need -fno-builtin. I can't remember quite which does which. In any event, here are *all* the link flags that I use to get .dlls out of GCC under Cygwin. I do this 100s of of times a day.
LFLAGS =
LFLAGS += -nostdlib
LFLAGS += -shared
LFLAGS += --entry=AEEMod_Load
ifdef STRIP_DEBUG_FROM_DLL
LFLAGS += --strip-debug# really handy to shrink down distributions
endif
LFLAGS_POST =
LFLAGS_POST += -L/usr/lib/gcc-lib/i686-pc-cygwin/$(GCC_VER)
LFLAGS_POST += -lgcc
Some of the command-line options must come near the end of the link command line. My link command looks like:
$(GCC_HOME)/ld $(LFLAGS) -o $(LFLAGS_POST)
With -fno-builtin, you have to provide your own implementations of things like memcpy(), free(), etc. I just forward mine to BREW's MEMCPY(), etc (except where I've replaced those with faster versions :) ).
Hope this helps!
-Jesse

-shared means you're trying to generate a .dll (or a .so, if you were targetting a unix, which you're not).
-static means you're trying to generate a .exe.
For BREW work, you definitely want -shared (and only -shared). The link problem can be fixed with -nostdlib.
Oh, wait. You have -nostdlib. Maybe you also need -fno-builtin. I can't remember quite which does which. In any event, here are *all* the link flags that I use to get .dlls out of GCC under Cygwin. I do this 100s of of times a day.
LFLAGS =
LFLAGS += -nostdlib
LFLAGS += -shared
LFLAGS += --entry=AEEMod_Load
ifdef STRIP_DEBUG_FROM_DLL
LFLAGS += --strip-debug# really handy to shrink down distributions
endif
LFLAGS_POST =
LFLAGS_POST += -L/usr/lib/gcc-lib/i686-pc-cygwin/$(GCC_VER)
LFLAGS_POST += -lgcc
Some of the command-line options must come near the end of the link command line. My link command looks like:
$(GCC_HOME)/ld $(LFLAGS) -o $(LFLAGS_POST)
With -fno-builtin, you have to provide your own implementations of things like memcpy(), free(), etc. I just forward mine to BREW's MEMCPY(), etc (except where I've replaced those with faster versions :) ).
Hope this helps!
-Jesse

Ah, thanks!
I *thought* -static and -shared should be mutually incompatible. For some reason all of the gcc dll makefiles floating around here in the BREW forums all had them both defined side by side in the link flags... weird... I wonder if previous versions of gcc/ld just quietly chose one over the other when both were listed. At one point I saw source code patches floating around in the gcc build forums for properly adding this error........
So for all missing stdlib symbols, just point them back to the native BREW versions?
Tx!
Sam

Ah, thanks!
I *thought* -static and -shared should be mutually incompatible. For some reason all of the gcc dll makefiles floating around here in the BREW forums all had them both defined side by side in the link flags... weird... I wonder if previous versions of gcc/ld just quietly chose one over the other when both were listed. At one point I saw source code patches floating around in the gcc build forums for properly adding this error........
So for all missing stdlib symbols, just point them back to the native BREW versions?
Tx!
Sam

Thanks! Got it compiling using Cygwin/MinGW/GCC/G++, on a batch of C++ flies, to create an emulator .dll. Now just have to set up the emulator to test it...
Here's the .h file with overridden functions I introduced to get it to link (and also redefinitions of new, delete, xca_pure_virtual, and assert, in order to use BREW's heap management, and avoid pulling in exceptions or RTTI):
extern "C" void __cxa_pure_virtual (void);
extern "C" void __assert( const char * , const char * , int );
extern "C" void* memcpy( void *s1, const void *s2, size_t n);
extern "C" void* memset ( void * buffer, int c, size_t num );
extern "C" int strcmp( const char * string1, const char * string2 );
void* operator new(size_t nBytes);
void operator delete(void * p);
void* operator new[](size_t nBytes);
void operator delete[](void * p);
Here'es the .cpp file:
void __cxa_pure_virtual (void) {}
void __assert(const char * , const char * , int ) {}
void* memcpy( void *s1, const void *s2, size_t n)
{
return MEMCPY( s1, s2, n);

int strcmp( const char * string1, const char * string2 )
{
return STRCMP( string1, string2);

void * memset ( void * buffer, int c, size_t num )
{
return MEMSET( buffer, c, num);

void * operator new(size_t nBytes)
{
return MALLOC(nBytes);

void operator delete(void * p)
{
FREE(p);

void * operator new[](size_t nBytes)
{
return MALLOC(nBytes);

void operator delete[](void * p)
{
FREE(p);

The dllMakefile I used is attached.
Sam

Thanks! Got it compiling using Cygwin/MinGW/GCC/G++, on a batch of C++ flies, to create an emulator .dll. Now just have to set up the emulator to test it...
Here's the .h file with overridden functions I introduced to get it to link (and also redefinitions of new, delete, xca_pure_virtual, and assert, in order to use BREW's heap management, and avoid pulling in exceptions or RTTI):
extern "C" void __cxa_pure_virtual (void);
extern "C" void __assert( const char * , const char * , int );
extern "C" void* memcpy( void *s1, const void *s2, size_t n);
extern "C" void* memset ( void * buffer, int c, size_t num );
extern "C" int strcmp( const char * string1, const char * string2 );
void* operator new(size_t nBytes);
void operator delete(void * p);
void* operator new[](size_t nBytes);
void operator delete[](void * p);
Here'es the .cpp file:
void __cxa_pure_virtual (void) {}
void __assert(const char * , const char * , int ) {}
void* memcpy( void *s1, const void *s2, size_t n)
{
return MEMCPY( s1, s2, n);

int strcmp( const char * string1, const char * string2 )
{
return STRCMP( string1, string2);

void * memset ( void * buffer, int c, size_t num )
{
return MEMSET( buffer, c, num);

void * operator new(size_t nBytes)
{
return MALLOC(nBytes);

void operator delete(void * p)
{
FREE(p);

void * operator new[](size_t nBytes)
{
return MALLOC(nBytes);

void operator delete[](void * p)
{
FREE(p);

The dllMakefile I used is attached.
Sam

Hi,
Strike "memset" and "memcpy" from your list of self-defined methods for compiling dlls with gcc. They're both defined in GCCResolver.c. Just add that to your dll makefile.
Sam

Hi,
Strike "memset" and "memcpy" from your list of self-defined methods for compiling dlls with gcc. They're both defined in GCCResolver.c. Just add that to your dll makefile.
Sam

splandorf wrote:
extern "C" void __cxa_pure_virtual (void);
extern "C" void __assert( const char * , const char * , int );
extern "C" void* memcpy( void *s1, const void *s2, size_t n);
extern "C" void* memset ( void * buffer, int c, size_t num );
extern "C" int strcmp( const char * string1, const char * string2 );
void* operator new(size_t nBytes);
void operator delete(void * p);
void* operator new[](size_t nBytes);
void operator delete[](void * p);
Here'es the .cpp file:
void __cxa_pure_virtual (void) {}
void __assert(const char * , const char * , int ) {}
//...
The dllMakefile I used is attached.
SamI ended up with a pair of almost identical files :).
I just remembered another critical flag to include: "-fcheck-new". Normally, C++ expects operator new() and operator new [] () to *either* return a non-zero, valid buffer *or* throw an exception.
-fcheck-new tells the compiler that operator new[](), etc, might return zero on failure rather than throwing an exception. This is important when you have constructors:
Consider code like this:
class Foo
{
int A, B, C;
public:
Foo (int a, int b, int c) :
A(a),B(b),C(c)
{
}
;
int a = 0, b = 1, c = 2;
Foo *foo = new Foo(a,b,c);
Imagine what life would be like if you had to worry about "(null == this)" in Foo::Foo(int,int,int)!
-fcheck-new is a CFLAG, not an LFLAG. Also consider using -fno-rtti, -fno-exceptions and -fno-unwind-tables. These are less critical, but they strip the dialect of C++ recognized by GCC down to something more like what we have in a BREW .MOD's execution context, and thereby help you catch too-much-C++ errors earlier.
-Jesse

splandorf wrote:
extern "C" void __cxa_pure_virtual (void);
extern "C" void __assert( const char * , const char * , int );
extern "C" void* memcpy( void *s1, const void *s2, size_t n);
extern "C" void* memset ( void * buffer, int c, size_t num );
extern "C" int strcmp( const char * string1, const char * string2 );
void* operator new(size_t nBytes);
void operator delete(void * p);
void* operator new[](size_t nBytes);
void operator delete[](void * p);
Here'es the .cpp file:
void __cxa_pure_virtual (void) {}
void __assert(const char * , const char * , int ) {}
//...
The dllMakefile I used is attached.
SamI ended up with a pair of almost identical files :).
I just remembered another critical flag to include: "-fcheck-new". Normally, C++ expects operator new() and operator new [] () to *either* return a non-zero, valid buffer *or* throw an exception.
-fcheck-new tells the compiler that operator new[](), etc, might return zero on failure rather than throwing an exception. This is important when you have constructors:
Consider code like this:
class Foo
{
int A, B, C;
public:
Foo (int a, int b, int c) :
A(a),B(b),C(c)
{
}
;
int a = 0, b = 1, c = 2;
Foo *foo = new Foo(a,b,c);
Imagine what life would be like if you had to worry about "(null == this)" in Foo::Foo(int,int,int)!
-fcheck-new is a CFLAG, not an LFLAG. Also consider using -fno-rtti, -fno-exceptions and -fno-unwind-tables. These are less critical, but they strip the dialect of C++ recognized by GCC down to something more like what we have in a BREW .MOD's execution context, and thereby help you catch too-much-C++ errors earlier.
-Jesse

Thanks!
I will add it.
Unfortunately, I seem to be stymied at the last step in moving over to an all-open-source development environment -- I can't seem to get Eclipse to launch the BREW_Emulator.exe as the debug target :(
Curious if you or anyone else has tried to debug BREW inside of Elicpse (and been successful???)
Tx!,
Sam
[ PS: how's MForma? ;) ]

Thanks!
I will add it.
Unfortunately, I seem to be stymied at the last step in moving over to an all-open-source development environment -- I can't seem to get Eclipse to launch the BREW_Emulator.exe as the debug target :(
Curious if you or anyone else has tried to debug BREW inside of Elicpse (and been successful???)
Tx!,
Sam
[ PS: how's MForma? ;) ]

I take it back... got it to work.... will post instructions if anyone's interested.

I take it back... got it to work.... will post instructions if anyone's interested.

splandorf wrote:Thanks!
Unfortunately, I seem to be stymied at the last step in moving over to an all-open-source development environment -- I can't seem to get Eclipse to launch the BREW_Emulator.exe as the debug target :(
I'm strictly an Emacs-Make-Ant-Sed-Awk-Grep-Python-Perl man myself. I don't go in for all this newfangled stuff like IDEs. I'm still suspicious about windows (with a lowercase 'w') and mice.
Emacs and GNU Make got me off proprietary tools, *except*:
1. ARM RVCT for BREW v1.2. GCC is an option now that QUALCOMM has (supposedly) spruced up BREWelf2mod.exe to handle big-endian and Thumb Mode... but since the cost is already sunk in the ARM compiler I haven't been motivated to look past it recently. Even then I'd still be dependent on BREWelf2mod.exe, which makes me uncomfortable.
2. QUALCOMM's brewrc.exe. Why didn't they include that in BREWsdk3.1.3? For that matter, why didn't they include it in BREWsdk1.1.0? Anyhow, I've been using my own resource file format for two years now, but I just added brewrc.exe to the build process to get rid of the damned .MIF editor. Love it.
splandorf wrote:[ PS: how's MForma? ;) ]Don't talk about Fight Club ;}
-Jesse

splandorf wrote:Thanks!
Unfortunately, I seem to be stymied at the last step in moving over to an all-open-source development environment -- I can't seem to get Eclipse to launch the BREW_Emulator.exe as the debug target :(
I'm strictly an Emacs-Make-Ant-Sed-Awk-Grep-Python-Perl man myself. I don't go in for all this newfangled stuff like IDEs. I'm still suspicious about windows (with a lowercase 'w') and mice.
Emacs and GNU Make got me off proprietary tools, *except*:
1. ARM RVCT for BREW v1.2. GCC is an option now that QUALCOMM has (supposedly) spruced up BREWelf2mod.exe to handle big-endian and Thumb Mode... but since the cost is already sunk in the ARM compiler I haven't been motivated to look past it recently. Even then I'd still be dependent on BREWelf2mod.exe, which makes me uncomfortable.
2. QUALCOMM's brewrc.exe. Why didn't they include that in BREWsdk3.1.3? For that matter, why didn't they include it in BREWsdk1.1.0? Anyhow, I've been using my own resource file format for two years now, but I just added brewrc.exe to the build process to get rid of the damned .MIF editor. Love it.
splandorf wrote:[ PS: how's MForma? ;) ]Don't talk about Fight Club ;}
-Jesse