Hi Przemek and all, I've implemented almost all your requests by now (at least I tried), so if you can invest some time in it I'd appreciate your feedback very much. [ First I recommend reading the relevant ChangeLog entries. ]
Of course I'd equally invite everyone on any platforms, with any compilers for similar testing and feedback. Most probably there are several gcc details which need further tweaking, but conceptually it should be about ready. And yeah, the code could now use a cleanup in the compiler rule definition part, we should probably have some generic internal representation of the rules, but first I'd like to see the full feature set we need to work with. Few missing parts are gtcrs and gtsln handling, some still missing syslibs, like X11, startup function detection, MAIN() override, and -n issue. Overall I feel that while harbour exe have to be compatible with Clipper command line to its fullest, with hbmk we have some freedom to depart from the heritage and by all standards a main entry function isn't a bad idea, I assume most non-heritage code has one, or it can be added in a minute, so, I'd rather make it the sane default here with an option to override it. Brgds, Viktor On Thu, Feb 19, 2009 at 1:43 AM, Przemyslaw Czerpak <dru...@acn.waw.pl>wrote: > 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 > Harbour@harbour-project.org > http://lists.harbour-project.org/mailman/listinfo/harbour >
_______________________________________________ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour