www-apache-bugdb mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ozgur urgenc <urg...@rocketmail.com>
Subject os-windows/6206: Compiling with BORLAND C++ BUILDER 4
Date Sun, 18 Jun 2000 02:06:14 GMT

>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 <apbugs@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!     ]
 
 


Mime
View raw message