2009-04-22 08:48 UTC+0200 Viktor Szakats (harbour.01 syenar hu)

+ Implemented .po to .hbl conversion inside hbmk2, with
    incremental feature (.hbl will only be regenerated if any
    .po file dependencies are newer). This is currently the
    default, no -inc switch is needed for that.
    You can specify .po files in the command line, in po=
    lines in .hbp files, output file is passed via -hbl= option.
    To handle multiple languages without hassle, you can use
    ${lng} macro in .po and .hbl filenames, plus pass the list
    of languages in -lng=<lang comma list> option:
    app_${lng}.po -hbl=lang/${lng}.hbl -lng=en,hu,sk,pl
    [ Actual .po -> .hbl conversion code was taken from hbi18n
    tool made by Przemek, with little modifications. ]
  ! Fixed to check included .res file timestamp, but not parse it.
  + Added macro support in libs= .hbp lines.
This commit is contained in:
Viktor Szakats
2009-04-22 06:54:54 +00:00
parent c5a3aaf70b
commit cca7fb705d
2 changed files with 179 additions and 12 deletions

View File

@@ -8,6 +8,22 @@
2009-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org)
*/
2009-04-22 08:48 UTC+0200 Viktor Szakats (harbour.01 syenar hu)
+ Implemented .po to .hbl conversion inside hbmk2, with
incremental feature (.hbl will only be regenerated if any
.po file dependencies are newer). This is currently the
default, no -inc switch is needed for that.
You can specify .po files in the command line, in po=
lines in .hbp files, output file is passed via -hbl= option.
To handle multiple languages without hassle, you can use
${lng} macro in .po and .hbl filenames, plus pass the list
of languages in -lng=<lang comma list> option:
app_${lng}.po -hbl=lang/${lng}.hbl -lng=en,hu,sk,pl
[ Actual .po -> .hbl conversion code was taken from hbi18n
tool made by Przemek, with little modifications. ]
! Fixed to check included .res file timestamp, but not parse it.
+ Added macro support in libs= .hbp lines.
2009-04-21 18:14 UTC+0200 Viktor Szakats (harbour.01 syenar hu)
* utils/hbmk2/hbmk2.prg
+ Added new CPU architecture filters: x86, x86_64, ia64, arm

View File

@@ -35,6 +35,7 @@
* bash script with similar purpose for gcc family.
* entry point override method and detection code for gcc.
* rtlink/blinker link script parsers.
* LoadPOFiles() and GenHbl().
*
* See COPYING for licensing terms.
*
@@ -301,6 +302,9 @@ FUNCTION hbmk( aArgs )
LOCAL s_lHB_PCRE := .T.
LOCAL s_lHB_ZLIB := .T.
LOCAL s_cMAIN := NIL
LOCAL s_aPO
LOCAL s_cHBL
LOCAL s_aLNG
LOCAL s_lCPP := NIL
LOCAL s_lSHARED := NIL
@@ -821,6 +825,9 @@ FUNCTION hbmk( aArgs )
s_cPROGDIR := NIL
s_cPROGNAME := NIL
s_cFIRST := NIL
s_aPO := {}
s_cHBL := NIL
s_aLNG := {}
/* Collect all command line parameters */
aParams := {}
@@ -858,6 +865,7 @@ FUNCTION hbmk( aArgs )
/* Process automatic control files. */
HBP_ProcessAll( lNOHBP,;
@s_aPO,;
@s_aLIBUSER,;
@s_aLIBUSERGT,;
@s_aLIBPATH,;
@@ -1022,6 +1030,20 @@ FUNCTION hbmk( aArgs )
HB_SYMBOL_UNUSED( s_nJOBS )
CASE Left( cParamL, 5 ) == "-lng="
cParam := SubStr( cParam, 6 )
IF ! Empty( cParam )
s_aLNG := ListToArray( cParam, "," )
ENDIF
CASE Left( cParamL, 5 ) == "-hbl="
cParam := SubStr( cParam, 6 )
IF ! Empty( cParam )
s_cHBL := PathSepToTarget( cParam )
ENDIF
CASE Left( cParamL, 6 ) == "-main="
IF IsValidHarbourID( cParam := SubStr( cParam, 7 ) )
@@ -1219,6 +1241,7 @@ FUNCTION hbmk( aArgs )
ENDIF
HBP_ProcessOne( cParam,;
@s_aPO,;
@s_aLIBUSER,;
@s_aLIBUSERGT,;
@s_aLIBPATH,;
@@ -1293,6 +1316,16 @@ FUNCTION hbmk( aArgs )
DEFAULT s_cFIRST TO PathSepToSelf( cParam )
NEXT
CASE FN_ExtGet( cParamL ) == ".po"
FOR EACH cParam IN FN_Expand( PathProc( cParam, aParam[ _PAR_cFileName ] ) )
AAdd( s_aPO, PathSepToTarget( cParam ) )
NEXT
CASE FN_ExtGet( cParamL ) == ".hbl"
s_cHBL := PathSepToTarget( cParam )
OTHERWISE
IF ! Empty( cParam )
@@ -2546,6 +2579,10 @@ FUNCTION hbmk( aArgs )
s_aRESSRC_TODO := s_aRESSRC
ENDIF
IF Len( s_aPO ) > 0 .AND. ! s_lCLEAN
MakeHBL( s_aPO, s_cHBL, s_aLNG )
ENDIF
IF Len( s_aRESSRC_TODO ) > 0 .AND. ! Empty( cBin_Res ) .AND. ! s_lCLEAN
IF s_lINC .AND. ! s_lQuiet
@@ -3115,6 +3152,7 @@ STATIC FUNCTION FindNewerHeaders( cFileName, cParentDir, tTimeParent, lIncTry, l
LOCAL tTimeSelf
LOCAL tmp
LOCAL cNameExtL
LOCAL cExt
STATIC s_aExcl := { "windows.h", "ole2.h", "os2.h" }
@@ -3135,12 +3173,6 @@ STATIC FUNCTION FindNewerHeaders( cFileName, cParentDir, tTimeParent, lIncTry, l
RETURN .F.
ENDIF
/* Filter out non-source format inputs for MinGW / windres */
IF s_cCOMP $ "gcc|gpp|mingw|mingw64|mingwarm|cygwin" .AND. s_cARCH $ "win|wce" .AND. ;
Lower( FN_ExtGet( cFileName ) ) == ".res"
RETURN .F.
ENDIF
/* Don't spend time on some known headers */
cNameExtL := Lower( FN_NameExtGet( cFileName ) )
IF AScan( s_aExcl, { |tmp| Lower( tmp ) == cNameExtL } ) > 0
@@ -3173,6 +3205,15 @@ STATIC FUNCTION FindNewerHeaders( cFileName, cParentDir, tTimeParent, lIncTry, l
ENDIF
ENDIF
cExt := Lower( FN_ExtGet( cFileName ) )
/* Filter out non-source format inputs for MinGW / windres */
IF s_cCOMP $ "gcc|gpp|mingw|mingw64|mingwarm|cygwin" .AND. s_cARCH $ "win|wce" .AND. cExt == ".res"
RETURN .F.
ENDIF
/* TODO: Add filter based on extension to avoid binary files */
/* NOTE: Beef up this section if you need a more intelligent source
parser. Notice that this code is meant to process both
.prg, .c and .res sources. Please try to keep it simple,
@@ -3251,7 +3292,7 @@ STATIC FUNCTION FindLib( cLib, aLIBPATH, cLibExt )
LOCAL cDir
LOCAL tmp
/* Check libnames containing dirs */
/* Check libs in their full paths */
IF s_cCOMP $ "msvc|msvc64|msvcarm|bcc|pocc|pocc64|poccarm|owatcom"
IF ! Empty( FN_DirGet( cLib ) )
IF hb_FileExists( cLib := FN_ExtSet( cLib, cLibExt ) )
@@ -3517,12 +3558,12 @@ STATIC FUNCTION ArrayToList( array, cSeparator )
RETURN cString
STATIC FUNCTION ListToArray( cList )
STATIC FUNCTION ListToArray( cList, cSep )
LOCAL array := {}
LOCAL cItem
IF ! Empty( cList )
FOR EACH cItem IN hb_ATokens( cList )
FOR EACH cItem IN hb_ATokens( cList, cSep )
AAddNotEmpty( array, cItem )
NEXT
ENDIF
@@ -3771,6 +3812,7 @@ STATIC FUNCTION FN_HasWildcard( cFileName )
#define HBMK_CFG_NAME "hbmk.cfg"
STATIC PROCEDURE HBP_ProcessAll( lConfigOnly,;
/* @ */ aPO,;
/* @ */ aLIBUSER,;
/* @ */ aLIBUSERGT,;
/* @ */ aLIBPATH,;
@@ -3817,6 +3859,7 @@ STATIC PROCEDURE HBP_ProcessAll( lConfigOnly,;
OutStd( "hbmk: Processing configuration: " + cFileName + hb_osNewLine() )
ENDIF
HBP_ProcessOne( cFileName,;
@aPO,;
@aLIBUSER,;
@aLIBUSERGT,;
@aLIBPATH,;
@@ -3853,6 +3896,7 @@ STATIC PROCEDURE HBP_ProcessAll( lConfigOnly,;
OutStd( "hbmk: Processing: " + cFileName + hb_osNewLine() )
ENDIF
HBP_ProcessOne( cFileName,;
@aPO,;
@aLIBUSER,;
@aLIBUSERGT,;
@aLIBPATH,;
@@ -3886,6 +3930,7 @@ STATIC PROCEDURE HBP_ProcessAll( lConfigOnly,;
#define _EOL Chr( 10 )
STATIC PROCEDURE HBP_ProcessOne( cFileName,;
/* @ */ aPO,;
/* @ */ aLIBUSER,;
/* @ */ aLIBUSERGT,;
/* @ */ aLIBPATH,;
@@ -3926,9 +3971,17 @@ STATIC PROCEDURE HBP_ProcessOne( cFileName,;
cLine := AllTrim( ArchCompFilter( AllTrim( cLine ) ) )
DO CASE
CASE Lower( Left( cLine, Len( "po=" ) ) ) == "po=" ; cLine := SubStr( cLine, Len( "po=" ) + 1 )
FOR EACH cItem IN hb_ATokens( cLine,, .T. )
cItem := PathSepToTarget( MacroProc( StrStripQuote( cItem ), FN_DirGet( cFileName ) ) )
IF AScan( aPO, {|tmp| tmp == cItem } ) == 0
AAddNotEmpty( aPO, cItem )
ENDIF
NEXT
CASE Lower( Left( cLine, Len( "libs=" ) ) ) == "libs=" ; cLine := SubStr( cLine, Len( "libs=" ) + 1 )
FOR EACH cItem IN hb_ATokens( cLine,, .T. )
cItem := PathSepToTarget( StrStripQuote( cItem ) )
cItem := PathSepToTarget( MacroProc( StrStripQuote( cItem ), FN_DirGet( cFileName ) ) )
IF AScan( aLIBUSER, {|tmp| tmp == cItem } ) == 0
AAddNotEmpty( aLIBUSER, cItem )
ENDIF
@@ -4683,6 +4736,99 @@ STATIC FUNCTION rtlnk_process( cCommands, cFileOut, aFileList, aLibList, ;
RETURN .T.
/* .hbl generation */
#define _LNG_MARKER "${lng}"
STATIC PROCEDURE MakeHBL( aPO, cHBL, aLNG )
LOCAL cPO
LOCAL tPO
LOCAL cLNG
LOCAL tLNG
LOCAL aPO_TODO
IF ! Empty( aPO )
IF s_lDEBUG
OutStd( "hbmk: PO: in: ", ArrayToList( aPO ), hb_osNewLine() )
ENDIF
IF Empty( cHBL )
cHBL := FN_NameGet( aPO[ 1 ] )
ENDIF
IF Empty( FN_ExtGet( cHBL ) )
cHBL := FN_ExtSet( cHBL, ".hbl" )
ENDIF
IF Empty( aLNG )
tLNG := NIL
hb_FGetDateTime( cHBL, @tLNG )
aPO_TODO := {}
FOR EACH cPO IN aPO
IF !( _LNG_MARKER $ cPO ) .AND. ( tLNG == NIL .OR. ( hb_FGetDateTime( cPO, @tPO ) .AND. tPO > tLNG ) )
AAdd( aPO_TODO, cPO )
ENDIF
NEXT
IF ! Empty( aPO_TODO )
IF s_lDEBUG
OutStd( "hbmk: PO: ", ArrayToList( aPO_TODO ), "->", cHBL, hb_osNewLine() )
ENDIF
GenHbl( aPO_TODO, cHBL )
ENDIF
ELSE
FOR EACH cLNG IN aLNG
tLNG := NIL
hb_FGetDateTime( StrTran( cHBL, _LNG_MARKER, cLNG ), @tLNG )
aPO_TODO := {}
FOR EACH cPO IN aPO
IF _LNG_MARKER $ cPO .AND. ( tLNG == NIL .OR. ( hb_FGetDateTime( StrTran( cPO, _LNG_MARKER, cLNG ), @tPO ) .AND. tPO > tLNG ) )
AAdd( aPO_TODO, StrTran( cPO, _LNG_MARKER, cLNG ) )
ENDIF
NEXT
IF ! Empty( aPO_TODO )
IF s_lDEBUG
OutStd( "hbmk: PO: ", ArrayToList( aPO_TODO ), "->", StrTran( cHBL, _LNG_MARKER, cLNG ), hb_osNewLine() )
ENDIF
GenHbl( aPO_TODO, StrTran( cHBL, _LNG_MARKER, cLNG ) )
ENDIF
NEXT
ENDIF
ENDIF
RETURN
STATIC FUNCTION LoadPOFiles( aFiles )
LOCAL aTrans, aTrans2
LOCAL cErrorMsg
LOCAL n
aTrans := __I18N_potArrayLoad( aFiles[ 1 ], @cErrorMsg )
IF aTrans == NIL
OutStd( "hbmk: .po error: ", cErrorMsg, hb_osNewLine() )
ENDIF
FOR n := 2 TO Len( aFiles )
aTrans2 := __I18N_potArrayLoad( aFiles[ n ], @cErrorMsg )
IF aTrans2 == NIL
OutStd( "hbmk: .po error: ", cErrorMsg, hb_osNewLine() )
ELSE
__I18N_potArrayJoin( aTrans, aTrans2 )
ENDIF
NEXT
RETURN aTrans
STATIC PROCEDURE GenHbl( aFiles, cFileOut, lEmpty )
LOCAL cHblBody
LOCAL pI18N
LOCAL aTrans := LoadPOFiles( aFiles )
IF ISARRAY( aTrans )
pI18N := __I18N_hashTable( __I18N_potArrayToHash( aTrans, lEmpty ) )
cHblBody := HB_I18N_SaveTable( pI18N )
IF ! hb_memoWrit( cFileOut, cHblBody )
OutStd( "hbmk: Cannot create file: ", cFileOut, hb_osNewLine() )
ENDIF
ENDIF
RETURN
/* Keep this public, it's used from macro. */
FUNCTION hbmk_ARCH()
RETURN s_cARCH
@@ -4750,7 +4896,7 @@ STATIC PROCEDURE ShowHeader()
STATIC PROCEDURE ShowHelp( lLong )
LOCAL aText_Basic := {;
"Syntax: hbmk [options] [<script[s]>] <src[s][.prg|.c|.obj|.o|.rc|.res]>" ,;
"Syntax: hbmk [options] [<script[s]>] <src[s][.prg|.c|.obj|.o|.rc|.res|.po]>" ,;
"" ,;
"Options:" ,;
" -o<outname> output file name" ,;
@@ -4801,6 +4947,11 @@ STATIC PROCEDURE ShowHelp( lLong )
" -clean clean (in incremental build mode)" ,;
" -workdir=<dir> working directory for incremental build mode" ,;
" (default: arch/comp)" ,;
" -hbl=<output> output .hbl filename. ${lng} macro is accepted in filename" ,;
" -lng=<languages> list of languages to be replaced in ${lng} macros in .po" ,;
" filenames and output .hbl filenames. Comma separared list:" ,;
" -lng=en-EN,hu-HU,de" ,;
"" ,;
" -hbcmp|-clipper stop after creating the object files" ,;
" create link/copy hbmk to hbcmp/clipper for the same effect" ,;
" -hbcc stop after creating the object files and accept raw C flags" ,;
@@ -4838,7 +4989,7 @@ STATIC PROCEDURE ShowHelp( lLong )
" - .hbp options (they should come in separate lines):" ,;
" libs=[<libname[s]>], gt=[gtname], prgflags=[Harbour flags]" ,;
" cflags=[C compiler flags], resflags=[resource compiler flags]" ,;
" ldflags=[Linker flags], libpaths=[paths]," ,;
" ldflags=[Linker flags], libpaths=[paths], po=[.po files]" ,;
" incpaths=[paths], inctrypaths=[paths]" ,;
" gui|mt|shared|nulrdd|debug|opt|map|strip|run|inc=[yes|no]" ,;
" compr=[yes|no|def|min|max], head=[off|partial|full], echo=<text>" ,;