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

Reply via email to