Hi Viktor,
I've just tried hbmk2.prg and I have few notes about it.
1. the C compiler auto detection should be extended to use also
compiler used to compile Harbour.
This is peace of code I was using from my hb-tools.prg:
if empty( s_hb_compiler )
cEnv := getEnv( "HB_COMPILER" )
if !empty( cEnv )
s_hb_compiler := cEnv
else
cEnv := hb_compiler()
if ( "Borland" $ cEnv .or. "CodeGear" $ cEnv ) .and. ;
isExecutable( s_hb_ccprefix + "bcc32" )
s_hb_compiler := "bcc32"
elseif "DJGPP" $ cEnv .and. isExecutable( s_hb_ccprefix + "gcc" )
s_hb_compiler := "djgpp"
elseif "MinGW" $ cEnv .and. isExecutable( s_hb_ccprefix + "gcc" )
s_hb_compiler := "mingw"
elseif "GNU C++" $ cEnv .and. isExecutable( s_hb_ccprefix + "g++" )
s_hb_compiler := "g++"
elseif "GNU C" $ cEnv .and. isExecutable( s_hb_ccprefix + "gcc" )
s_hb_compiler := "gcc"
elseif "Watcom C++" $ cEnv .and. isExecutable( s_hb_ccprefix +
"wpp386" )
s_hb_compiler := "wpp386"
elseif "Watcom C" $ cEnv .and. isExecutable( s_hb_ccprefix +
"wcc386" )
s_hb_compiler := "wcc386"
elseif "(XCC)" $ cEnv .and. isExecutable( s_hb_ccprefix + "xcc" )
s_hb_compiler := "xcc"
elseif "Pelles ISO C" $ cEnv .and. isExecutable( s_hb_ccprefix +
"pocc" )
s_hb_compiler := "pocc"
elseif "Digital Mars" $ cEnv .and. isExecutable( s_hb_ccprefix +
"dmc" )
s_hb_compiler := "dmc"
elseif "Microsoft Visual C" $ cEnv .and. isExecutable(
s_hb_ccprefix + "cl" )
s_hb_compiler := "msvc"
endif
endif
endif
/* in few cases compiler can be used only with single platform so we
* can always set it here overloading any auto detections
*/
switch s_hb_compiler
case "mingw"
case "mingwce"
case "bcc32"
case "xcc"
case "pocc"
case "dmc"
case "msvc"
s_hb_arch := "win"
exit
case "djgpp"
s_hb_arch := "dos"
exit
endswitch
static function isExecutable( cExecName )
return findExecutable( cExecName ) != NIL
static function findExecutable( cExecName )
local cFile, cPath, cExt
hb_FNameSplit( cExecName,, @cExecName, @cExt )
#if defined( __PLATFORM__DOS ) .or. ;
defined( __PLATFORM__WINDOWS ) .or. ;
defined( __PLATFORM__OS2 )
if empty( cExt )
cExt := ".exe"
endif
#endif
hb_FNameSplit( hb_argv( 0 ), @cPath )
if !empty( cPath )
cFile := hb_FNameMerge( cPath, cExecName, cExt )
if hb_fileExists( cFile )
return cFile
endif
endif
for each cPath in hb_aTokens( getEnv( "PATH" ), hb_osPathListSeparator() )
cFile := hb_FNameMerge( cPath, cExecName, cExt )
if hb_fileExists( cFile )
return cFile
endif
next
return NIL
2. install dir auto detection should be updated.
In general we have two version of installation:
a)
<basdir>/bin
<basdir>/include
<basdir>/lib
b)
<basdir>/bin
<basdir>/include/harbour
<basdir>/lib/harbour
so I was using this code:
if !empty( s_hb_hbexe )
hb_FNameSplit( s_hb_hbexe, @cBinPath )
if right( cBinPath, 1 ) $ hb_osPathDelimiters()
cBinPath := left( cBinPath, len( cBinPath ) - 1 )
endif
hb_FNameSplit( cBinPath, @cPath, @cName )
if lower( cName ) == "bin"
if !right( cPath, 1 ) $ hb_osPathDelimiters()
cPath += hb_osPathSeparator()
endif
if hb_dirExists( cPath + "lib" ) .and. hb_dirExists( cPath +
"include" )
if isLib( "hbvm", cPath + "lib" ) .and. ;
hb_fileExists( cPath + "include" + hb_osPathSeparator() +
"hbvm.h" )
s_hb_bindir := cBinPath
s_hb_libdir := cPath + "lib"
s_hb_incdir := cPath + "include"
elseif isLib( "hbvm", cPath + "lib" + hb_osPathSeparator() + ;
"harbour" ) .and. ;
hb_fileExists( cPath + "include" +
hb_osPathSeparator() + ;
"harbour" + hb_osPathSeparator() +
"hbvm.h" )
s_hb_bindir := cBinPath
s_hb_libdir := cPath + "lib" + hb_osPathSeparator() +
"harbour"
s_hb_incdir := cPath + "include" + hb_osPathSeparator() +
"harbour"
endif
endif
endif
endif
static function isLib( cLib, cPath )
return hb_fileExists( iif( cPath == NIL, s_hb_libdir, cPath ) + ;
hb_osPathSeparator() + ;
s_hb_libpfx + cLib + s_hb_libext )
3. in *nixes GTCGI have to be used as GT driver in hbmk.prg
otherwise output from external command is lost. Probably
it should be default also for all other platforms.
4. Such tool should be as invisible as possible so it should not
any additional information until not explicitly requested by
some switch, f.e. -verbose or sth like that to not mix the
default output from executed compilers.
It will be good to have additional verbose level in which
executed command are shown before running compiler application
to verify final results, f.e. options included by -bldflags
5. non of Harbour compiler options ( -n -q -w -es2, ...) should
be enabled by default except the options necessary to compile
the code: -I<HarbourIncludeDir>, -D<crossBuildDefines>,
-undef:<crossBuildDefines> and of course -gc[0-3] to force .c
output but only if user does not specify other form, f.e. -gh.
6. -bldflags should be probably divided into C flags and .prg
flags. User may use completely different .prg flags then the ones
we used to build Harbour but need C flags which can be necessary
to create valid binaries.
It will be also good to add automatic support for inheriting some
C flags we know that are always necessary to create valid binaries,
f.e. -m32/-m64 on some platforms which can create 32 or 64 bit
binaries. For GCC I was always using this flags:
if s_hb_cc == "gcc" .or. s_hb_cc == "g++"
if "-mlp64" $ s_hb_bldflags
s_hb_cc_opt -= " -mlp64"
elseif "-mlp32" $ s_hb_bldflags
s_hb_cc_opt -= " -mlp32"
elseif "-m64" $ s_hb_bldflags
s_hb_cc_opt -= " -m64"
elseif "-m32" $ s_hb_bldflags
s_hb_cc_opt -= " -m32"
endif
if "-fPIC" $ s_hb_bldflags
s_hb_cc_opt -= " -fPIC"
elseif "-fpic" $ s_hb_bldflags
s_hb_cc_opt -= " -fpic"
endif
endif
7. output file name auto detection should respect the compilation
mode, f.e. hbmk -cmp a.prg it should generate a.{o,obj} not 'a'
or 'a.exe'
8. When -l<libname> gcc option is used then <libname> should
not contain prefix (lib) and extension (.so,.dll,.a)
9. We should have support for passing object archives (.a) in
link file list and then pass it to GCC without -l parameter.
Using 'mylib.a' and '-lmylib' as GCC parameters has different
meaning so mylib.a should not be converted to -lmylib but simply
passed to GCC as is.
10. In GCC builds on platforms which support
-Wl,--start-group <HARBOUR_LIBS> -Wl,--end-group
(linux, mingw) we should use it to not replicate libraries with
cross bindings.
BTW current library list is not well ordered so it's not possible
to create some binaries, f.e. try hbmk hbrun.prg in some GCC builds.
It has to be updated for platforms which does not support above
library grouping.
11. There is no support for automatic main function detection in GCC
builds. This code extracts 1-st function name from the 1-st linked
file in my hb-tools.prg. It can receive the name of .c file generated
from .prg file or .o file name but in such case it works only for
gcc/g++ based compilers (it uses nm tool).
/* in GCC LD (except DJGPP) the order of registering init function
* does not depend directly on the order of linked files. If we want
* to inform HVM about valid startup function then we should try to
* locate it ourselves and pass it to HVM using our startup function
*/
static func getFirstFunc( cFile )
local cFuncList, cExecNM, cFuncName, cExt, cLine, n, c
cFuncName := ""
if ( s_hb_cc == "gcc" .or. s_hb_cc == "g++" ) .and. !s_hb_compiler ==
"djgpp"
hb_FNameSplit( cFile,,, @cExt )
if cExt == ".c"
for each cLine in hb_aTokens( strtran( memoread( cFile ), chr(
13 ), chr( 10 ) ), chr( 10 ) )
cLine := alltrim( cLine )
if cLine = '{ "' .and. "HB_FS_FIRST" $ cLine
n := 4
while ( c := substr( cLine, n++, 1 ) ) != '"'
cFuncName += c
enddo
exit
endif
next
elseif !empty( cExecNM := findExecutable( s_hb_ccprefix + "nm" ) )
cFuncList := commandResult( cExecNM + " " + cFile + " -g -n
--defined-only -C" )
if ( n := at( " T HB_FUN_", cFuncList ) ) != 0
n += 10
while ( c := substr( cFuncList, n++, 1 ) ) = "_" .or. ;
isdigit( c ) .or. isAlpha( c )
cFuncName += c
enddo
endif
endif
endif
return cFuncName
static function commandResult( cCommand, nResult )
local hFile, cFileName, cResult
hFile := hb_FTempCreate( ,,, @cFileName )
if hFile == -1
outErr( "Error: cannot create temporary file" + EOL )
break
endif
fclose( hFile )
cCommand += ">" + cFileName
nResult := hb_run( cCommand )
cResult := memoRead( cFileName )
ferase( cFileName )
return cResult
when we will have fully functional hbmk.prg then we can change
the startup code and replace current -n1 and default support
for HB_FS_FIRST. HB_FS_FIRST will be generated only by new explicit
switch which will be used by hbmk for 1-st file only.
12. hbdebug and hbcplr libraries are not part of Harbour shared library
and always should be added as static libraries even when harbour
shared library is used
13. the -o can point also to directory name not only file. hbmk.prg
should respect it and check the type of destination. Some C compilers
does not support -o as directory name so they will need different
calling if more then one .c file is passed in single command, f.e.
explicitly used chdir. Harbour compiler support -o as directory name
if the last character is path separator, f.e.:
harbour test.prg -ooutdir/
it would be very nice if hbmk.prg can use -o<dir> also for temporary
C files.
HTH and thank you for your job.
best regards,
Przemek
_______________________________________________
Harbour mailing list
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour