You are viewing a plain text version of this content. The canonical link for it is here.
Posted to apache-bugdb@apache.org by ozgur urgenc <ur...@rocketmail.com> on 2000/06/18 04:06:14 UTC

os-windows/6206: Compiling with BORLAND C++ BUILDER 4

>Number:         6206
>Category:       os-windows
>Synopsis:       Compiling with BORLAND C++ BUILDER 4
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    apache
>State:          open
>Class:          change-request
>Submitter-Id:   apache
>Arrival-Date:   Sat Jun 17 19:10:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     urgenc@rocketmail.com
>Release:        1.3.12
>Organization:
apache
>Environment:
Windows2000 Server , Borland C++ Builder 4
>Description:

How can I build Apache.exe and ApacheCore.dll with my beloved compiler Borland C++ Builder 4 ?
>How-To-Repeat:

>Fix:
How to Compile and Run Apache 1.3.12 HTTP server using BORLAND C++ BUILDER 4

by Ozgur Urgenc 2000-06-16  Istanbul
urgenc@rocketmail.com

I have to mention that
THE INSTRUCTIONS BELOW ARE NOT GUARANTEED TO WORK, 
THEY ARE JUST MY EXPERIENCE.  I MAY HAVE SKIPPED SOMETHING OR MISTAKEN UNINTENTIONALLY WHEN WRITING IT DOWN.  YOU MAY EVEN FAIL TO BUILD THE TARGET EXECUTABLES. 
I DID NOT APPLIED STRICT TESTS TO THE RESULTING EXECUTABLES, 
SO IT IS YOUR OWN RISK TO USE THE RESULTING EXECUTABLES.
 I AM NOT RESPONSIBLE FOR ANY LOSS ( TIME, MONEY, HEALTH, CONFIDENCE.....) AS A CONSEQUENCE OF THE INSTRUCTIONS AND CODE FRAGMENTS BELOW.


NOTE : this documentation is acompanied by modifiedfilesforBCB4.zip in which there is modified or newly created source code to Apache `1.3.12

I downloaded Apache 1.3.12 source code , modified some portions, compiled, linked and run the server. It took my 10 hours of hardworking. Eventually it worked. I did not applied strict tests to the executable created by Builder , however , it seems to work . Later on, I even linked and tested the mod_example module.  

Here is the steps :
I renamed �main\alloc.c� and �include\alloc.h� as �main\ap_alloc.c� and �include\ap_alloc.h�, modified all the refereces to alloc.h as ap_alloc.h. I did this because another alloc.h is deployed with BCB 4 which results in a confusion while compiling. The files which references alloc.h are :
Httpd.h ( #include �alloc.h� )

I created three projects : 

ap/Ap.lib which includes  
	Ap.bpr ( + Ap.cpp ) 
	ap_cpystrn.c
	ap_fnmatch.c
	ap_md5c.c
	ap_signal.c
	ap_slack.c
	ap_snprintf.c
	ap_sha1.c
	ap_base64.c
	ap_checkpass.c
	os.c ( newly created file , see Modification in Os.h below)
	ap_ctype.c ( newly created file , see Modification in ap_ctype.h below)

ApacheCore.dll which includes
	ap_alloc.c ( alloc.c renamed as apalloc )
	buff.c
	buildmark.c
	getopt.c
	http_config.c
	http_core.c
	http_log.c
	http_main.c
	http_protocol.c
	http_request.c
	http_vhost.c
	mod_access.c
	mod_actions.c
	mod_alias.c
	mod_asis.c
	mod_auth.c
	mod_autoindex.c
	mod_cgi.c
	mod_dir.c
	mod_env.c
	mod_imap.c
	mod_include.c
	mod_isapi.c
	mod_log_config.c
	mod_mime.c
	mod_negotiation.c
	mod_setenvif.c
	mod_so.c
	mod_userdir.c
	modules.c
	multithread.c
	readdir.c
	registry.c
	rfc1413.c
	service.c
	util.c
	util_date.c
	util_md5.c
	util_script.c
	util_uri.c
	util_win32.c
	ap.lib ( after building ap.lib)
	\Borland\CBuilder4\Lib\ws2_32.lib  ( I dont know why the sockets library is not linked by default )

Apache.exe ( console application ) which includes
	Apache.bpr ( + Apache.cpp ) 
	ApacheCore.lib ( after building ApacheCore.dll )

For all the projects above :
I added �../include� to include directories option of the project.
I defined WIN32;_WINDOWS;WIN32_LEAN_AND_MEAN;__MSC in project's defines
I set the warnings in the compiler options to "selected warnings" 

I found "uri_delims.h" and "test_char.h" and put them into the main/ directory.  If I had not found them, I would generate "uri_delims.h" using gen_uri_delims.c and would generate "test_char.h" using gen_test_char.c.

I modified some files :

Modifications in the os/win32/Os.h :
Enclosed the lines below within �#ifndef __BORLANDC__� �#endif� block:

#ifndef __BORLANDC__
typedef int mode_t;
#endif

#ifndef __BORLANDC__
#define S_ISREG(m) ((m & _S_IFREG) == _S_IFREG)
#endif


Enclosed the macros below :

#ifndef O_CREAT
#define O_CREAT _O_CREAT
#endif

#ifndef O_RDWR
#define O_RDWR _O_RDWR
#endif


added the macro below:

#ifndef _P_NOWAIT
#define _P_NOWAIT P_NOWAIT
#endif

Redefined export types :

#ifdef __BORLANDC__

#ifdef __DLL__
#define API_VAR_EXPORT            __declspec(dllexport)
#define API_EXPORT(type)          type __export
#define API_EXPORT_NONSTD(type)   type __export
#define MODULE_VAR_EXPORT         __declspec(dllexport)
#else
#define API_VAR_EXPORT
#define API_EXPORT(type)          type
#define API_EXPORT_NONSTD(type)   type
#define MODULE_VAR_EXPORT
#endif

#else   // not __BORLANDC__

#ifdef SHARED_MODULE
# define API_VAR_EXPORT		__declspec(dllimport)
# define API_EXPORT(type)    __declspec(dllimport) type __stdcall
# define API_EXPORT_NONSTD(type)    __declspec(dllimport) type
#else
# define API_VAR_EXPORT		__declspec(dllexport)
# define API_EXPORT(type)    __declspec(dllexport) type __stdcall
# define API_EXPORT_NONSTD(type)    __declspec(dllexport) type
#endif
#define MODULE_VAR_EXPORT   __declspec(dllexport)

#endif // __BORLANDC__

I created an Os.c file in the directory of os.h and moved the body of ap_os_is_path_absolute(const char *file) into that file from Os.h. This is so bacause Builder cannot create inline code in headerfile, so I stripped the __inline keyword. Enclosed the orginal definition in the os.h within #ifndef __BORLANDC__ clause, without forgetting to place prototype of the function in the #else block :
#ifndef __BORLANDC__
__inline int ap_os_is_path_absolute(const char *file)
{
/* For now, just do the same check that http_request.c and mod_alias.c
* do.
*/
return file[0] == '/' || file[1] == ':';
}
#else
int ap_os_is_path_absolute(const char *file);
#endif

os/win32/Os.c looks like this :
#include "os.h"
int ap_os_is_path_absolute(const char *file)
{
/* For now, just do the same check that http_request.c and mod_alias.c
* do.
*/
return file[0] == '/' || file[1] == ':';
}


Modifications in include/c_type.h :
On MS-Windows NT 4.0 no modification were needed, however on Windows2000 Server the locale didnot worked properly, so , I rewrote all the macros defined in this file as functions in newly created ap\ap_ctype.c.  Enclosed the old macros within #ifndef __BORLANDC__ block whereas placed the function prototypes within the #else block.

ap/ap_ctype.c looks like that

#include <ap_ctype.h>

int     ap_isalnum(unsigned char c)
{ if( ap_islower(c) ) return 1;
  if( ap_isupper(c) ) return 1;
  if( ap_isdigit(c) ) return 1;
  return 0;
}

int     ap_isalpha(unsigned char c)
{ if( ap_islower(c) || ap_isupper(c) ) return 1;
  else                                 return 0;
}

int     ap_iscntrl(unsigned char c)
{
  if(c<'\x20')     return 1;
  if(c=='\x7f')    return 1;
  return 0;
}

int     ap_isdigit(unsigned char c)
{
  if((c>='0')&&(c<='9')) return 1;
  else                   return 0;
}

int     ap_isgraph(unsigned char c)
{
  if(c>'\x20') return 1;
  else         return 0;
}

int     ap_islower(unsigned char c)
{
  if((c>='a')&&(c<='z')) return 1;
  else                   return 0;
}

int     ap_isprint(unsigned char c)
{
  if(c>='\x20') return 1;
  else          return 0;
}

int     ap_ispunct(unsigned char c)
{
  if(!ap_isprint(c)) return 0;

  if(ap_isalnum(c)) return 0;
  if((c=='\x20'))   return 0;
  return 1;
}

int     ap_isspace(unsigned char c)
{
  if((c>='\x9')&&(c<='\xd')) return 1;
  if((c=='\x20'))            return 1;
  return 0;
}

int     ap_isupper(unsigned char c)
{
  if((c>='A')&&(c<='Z')) return 1;
  else                   return 0;
}

int     ap_isxdigit(unsigned char c)
{
  if((c>='0')&&(c<='9')) return 1;
  if((c>='a')&&(c<='f')) return 1;
  if((c>='A')&&(c<='F')) return 1;
  else                        return 0;
}

unsigned char ap_tolower(unsigned char c)
{
  if(ap_isupper(c))  c = c | 0x20;
  return c;
}

unsigned char ap_toupper(unsigned char c)
{
  if(ap_islower(c))  c = c & ~0x20;
  return c;
}

Looking up from a locale array is always faster than the functions above, but the difference in the performance is slight.  May be setting the locale at the startup of the server is another solution but I do not know whether it will work on Windows 2002,2005....., the functions above are much more safer.  Another method is setting up your own locale array.


Modifications in os/win32/readdir.c :

_findnext function behaves different from the way it is documented on Windows2000 Server. ( On NT 4.0 it works properly). According to the documentation it returns 0 on success,   -1 onfalilure, however, it actually returns 1 on success, 0 on failure.  Using _findnext(...)<=0 rather than _findnext<0 may solve the problem.  I suggest a more portable solution which is also efficent equally as well.  I set dp->fileinfo.name[0] as '\0' before calling the function and checked whether it has been changed after calling _findnext() . If there is something in dp->fileinfo.name it is success, if nothing in dp->fileinfo.name it is failure.  I applied this method to the _findfirst() also.

This code below :

    if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0) {
        if (errno == ENOENT)
            dp->finished = 1;
        else
        return NULL;
    }

became :

   *dp->fileinfo.name='\0';
    handle=_findfirst(filespec, &(dp->fileinfo));
    if ( !*dp->fileinfo.name) {
        if (errno == ENOENT)
            dp->finished = 1;
        else
        return NULL;
    }


This code below :

        if (_findnext(dp->handle, &(dp->fileinfo)) < 0) {
            dp->finished = 1;
            return NULL;
        }

became :

        *dp->fileinfo.name='\0';
        _findnext(dp->handle, &(dp->fileinfo));
        if ( ! *dp->fileinfo.name ) {
            dp->finished = 1;
            return NULL;
        }


Modifications in os/win32/multithread.c

I added the line below before the function body of create_thread(void (thread_fn)(void *), void *thread_arg):
typedef unsigned (__stdcall *TPThreadFunction)(void *);

Changed :
    rv = _beginthreadex(NULL, 0,
                                (LPTHREAD_START_ROUTINE)  thread_fn,
                                thread_arg, 0, &id);

As:
    rv = _beginthreadex( NULL, 0,
                                  (TPThreadFunction) thread_fn,
                                  thread_arg, 0, &id);


Modifications in os/win32/util_win32.c :

I inserted the lines below just before os_spawnv():

#ifdef __BORLANDC__
#define _spawnv spawnv
#endif

I inserted the lines below just before os_spawnve():

#ifdef __BORLANDC__
#define _spawnve spawnve
#endif


Modifications in main/http_main :

No modification, just suggestion:
As long as you are building all your executables yourself you may set any one of calling conventions __stdcall, __cdecl , __pascal or __fastcall as default. ( Project options -> Advanced Compiler -> Calling convention )  However, if you are interacting with other binaries such as module DLLs or Operating system you should be careful of prolog-epilog-name_mangling of the exportable objects.  _beginthreadex() expect a __stdcall function pointer. A __stdcall function expects parameters left-to-right order in the stack, also rollsback the stack pointer itself.  Fortunately in this case the function does not have a parameter, order is unimportant , since there is no parameters pushed into the stack, stack is rolled back by neither the caller nor the callee.  However this may cause problems if the convention changes for next versions of Windows, I suggest defining child_main() function as __stdcall explicitly.  Just a suggestion, you dont need to.

If you are not interested in compiling all the apache server code, just writing your module code as a DLL ( this is the case when I first interested in Apache )  be careful about the name mangling and calling convetions.  Borland usually prepends an '_' to the exported object names if default calling convention is "C".  ( it is not example_handler, it is _example_handler within the httpd.conf ).  I think the original binary from www.apache.org expects the entry points to be __stdcall.

Modifications in Apache.cpp :

An Apache.cpp is created by the BCB4 automatically.  I modified that file and it looks like that :

#pragma hdrstop
#include <condefs.h>

USELIB("ApacheCore.lib");
//---------------------------------------------------------------------------

#pragma argsused

//---------------------------------------------------------------------------
extern "C" {
int apache_main(int argc, char *argv[]);
}
//---------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    return apache_main(argc, argv);
}
//---------------------------------------------------------------------------


Builded ap.lib (ap.bpr) and received 4 warnings.
Builded ApacheCore.dll (ApacheCore.bpr) and received 264 warnings.
Builded Apache.exe (Apache.bpr) and received 0 warnings.

I set up conf/ , htdocs/ and logs/ directories.

To debug the ApacheCore.dll, I set host application as "Apache.exe" and parameters as "-X"

To link a module statically modify os/win32/modules.c.  How to modify this file is yet another case.


GOOD LUCK !...
>Release-Note:
>Audit-Trail:
>Unformatted:
 [In order for any reply to be added to the PR database, you need]
 [to include <ap...@Apache.Org> in the Cc line and make sure the]
 [subject line starts with the report component and number, with ]
 [or without any 'Re:' prefixes (such as "general/1098:" or      ]
 ["Re: general/1098:").  If the subject doesn't match this       ]
 [pattern, your message will be misfiled and ignored.  The       ]
 ["apbugs" address is not added to the Cc line of messages from  ]
 [the database automatically because of the potential for mail   ]
 [loops.  If you do not include this Cc, your reply may be ig-   ]
 [nored unless you are responding to an explicit request from a  ]
 [developer.  Reply only with text; DO NOT SEND ATTACHMENTS!     ]
 
 


RE: os-windows/6206: Compiling with BORLAND C++ BUILDER 4

Posted by "William A. Rowe, Jr." <wr...@lnd.com>.
> >Fix:
> How to Compile and Run Apache 1.3.12 HTTP server using 
> BORLAND C++ BUILDER 4
> 
> by Ozgur Urgenc 2000-06-16  Istanbul
> urgenc@rocketmail.com
 
Ozgur,

  Thank you!  It's so good to see someone interested in having
a borland based build environment for Apache!

  I say this because of the 'free' release of the BCC compiler
5.5, which does not include the 'builder' IDE environment.  It
is a great fit, but we need someone interested in identifing
the issues on the Borland platform.

  I will be in touch with you after I've reviewed your notes, 
and merged them into how the 1.3.13 build will be distributed.

  And thanks for your interest in the Apache project!