* contrib/xhb/hbcompat.ch
+ Added xhb translations for hb_eol() and hb_ps().
* contrib/make.hbs
- Deleted SetCancel().
* src/debug/tbrwtext.prg
* src/debug/debugger.prg
* src/rtl/errsys.prg
* src/rtl/profiler.prg
* src/rtl/hbini.prg
* src/rtl/treport.prg
* src/rtl/tpersist.prg
* src/rtl/hbi18n2.prg
* src/rtl/ttextlin.prg
* src/rtl/teditor.prg
* src/rdd/usrrdd/rdds/logrdd.prg
* tests/hbpptest/hbpptest.prg
* tests/longstr2.prg
* tests/cdow.prg
* tests/output.prg
* tests/dirtest.prg
* tests/tstdbi.prg
* tests/speedold.prg
* tests/dates3.prg
* tests/set_test.prg
* tests/rto_get.prg
* tests/cpinfo.prg
* tests/speedtst.prg
* tests/dates.prg
* tests/set_num.prg
* tests/rto_tb.prg
* tests/testhtml.prg
* tests/round.prg
* tests/dates2.prg
* tests/dates4.prg
* tests/version.prg
* tests/seconds.prg
* tests/gtkeys.prg
* tests/adirtest.prg
* include/simpleio.ch
* include/assert.ch
* contrib/hbct/tests/tab.prg
* contrib/hbct/tests/expomant.prg
* contrib/xhb/traceprg.prg
* contrib/xhb/hblog.prg
* contrib/xhb/dumpvar.prg
* contrib/xhb/dbgfx.prg
* contrib/xhb/xhberr.prg
* contrib/xhb/cstruct.prg
* contrib/hbqt/generator/hbqtgen.prg
* contrib/hbqt/hbqt_errorsys.prg
* contrib/hbqt/generator2/hbqtgen2.prg
* contrib/hbxpp/hbxpp.ch
* contrib/hbnetio/utils/netiosrv.prg
* contrib/hbnetio/utils/rpcdemo.hbs
* contrib/hbnetio/utils/netiocmd.prg
* contrib/hbpgsql/tests/dbf2pg.prg
* contrib/hbmisc/tests/readfile.prg
* contrib/hbmisc/tests/testhbf.prg
* contrib/hbtip/thtml.prg
* contrib/hbtip/client.prg
* contrib/hbwin/tests/testsim.prg
* contrib/hbwin/tests/testole.prg
* contrib/hbwin/tests/testsvc.prg
* contrib/hbssl/tests/bio.prg
* contrib/hbssl/tests/pem.prg
* contrib/hbide/ideedit.prg
* contrib/hbide/idemisc.prg
* contrib/hbide/idethemes.prg
* contrib/hbide/idesaveload.prg
* contrib/hbide/idedocwriter.prg
* contrib/hbide/hbide.ch
* contrib/hbide/ideprojmanager.prg
* contrib/hbide/idehome.prg
* contrib/hbide/ideshortcuts.prg
* utils/hbformat/hbformat.prg
* utils/hbmk2/hbmk2.prg
* utils/hbi18n/hbi18n.prg
* utils/hbtest/hbtest.prg
* examples/hbextern/hbextern.prg
* examples/uhttpd2/umain.prg
* examples/guestbk/inifiles.prg
* examples/guestbk/testcgi.prg
* examples/httpsrv/uhttpd.prg
* examples/hscript/hscript.prg
* hb_osnewline() -> hb_eol()
(deleting temp variables and temp pp macros used in the past
to workaround the long typing of the old function name)
* Some formatting along the way in tests dir.
* src/rtl/errsys.prg
- Deleted usage of ISNIL(). It's a quite pointless macro.
* src/rtl/errsys.prg
* src/rtl/listbox.prg
* src/rtl/profiler.prg
* src/rtl/treport.prg
* src/rtl/tpersist.prg
* src/rtl/tgetlist.prg
* src/rtl/teditor.prg
% DO CASE -> SWITCH
* src/rtl/alert.prg
* Replaced DEFAULT TO with simple NIL check.
* src/compiler/gencc.c
* Formatting of generated code.
* contrib/hbide/ideedit.prg
* contrib/hbide/idemisc.prg
* contrib/hbide/idethemes.prg
* contrib/hbide/idesaveload.prg
* contrib/hbide/idedocwriter.prg
* contrib/hbide/hbide.ch
* contrib/hbide/ideprojmanager.prg
* contrib/hbide/idehome.prg
* contrib/hbide/ideshortcuts.prg
* hb_osPathSeparator() (and static variable) -> hb_ps()
720 lines
21 KiB
Handlebars
Executable File
720 lines
21 KiB
Handlebars
Executable File
#!/usr/bin/hbrun --hb:gtcgi
|
|
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* Harbour Project source code:
|
|
* Package build orchestrator script
|
|
*
|
|
* Copyright 2010 Viktor Szakats (harbour.01 syenar.hu)
|
|
* www - http://harbour-project.org
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit
|
|
* their web site at http://www.gnu.org/).
|
|
*
|
|
*/
|
|
|
|
/* TODO:
|
|
1. normalize path to hbpre/hbpost to save on cmdline
|
|
2. solve HB_BUILD_CONTRIB_DLL support the .dlls are either
|
|
huge, or they don't link.
|
|
3. hbmk2 location detection in standalone mode
|
|
(or move hbmk2 to core lib?)
|
|
4. Move in external libs to contrib area? (bz2, minizip, sqlite3)
|
|
5. 'install' is ignored in stdalone mode. It would be needed to
|
|
replicate the install dir defaulting logic found in global.mk
|
|
to implement it.
|
|
6. Delete header install related logic from GNU Make system,
|
|
also delete doc/*.txt install related logic (easily replacable
|
|
with postinst.hbs logic)
|
|
7. Move some logic to hbmk2.
|
|
8. Honor paths found in --hbinfo hbctree{{}} section.
|
|
*/
|
|
|
|
#pragma warninglevel=3
|
|
|
|
/* TOFIX: Ugly hack to avoid #include "directry.ch" */
|
|
#define F_NAME 1 /* File name */
|
|
#define F_ATTR 5 /* File attribute */
|
|
|
|
#define _ACT_CLEAN 1
|
|
#define _ACT_INC 2
|
|
#define _ACT_INC_INST 3
|
|
#define _ACT_INC_REBUILD_INST 4
|
|
|
|
STATIC hActions := {;
|
|
_ACT_CLEAN => "clean" ,;
|
|
_ACT_INC => "build" ,;
|
|
_ACT_INC_INST => "build and install" ,;
|
|
_ACT_INC_REBUILD_INST => "rebuild and install" }
|
|
|
|
STATIC s_cBase
|
|
STATIC s_cHome
|
|
STATIC s_cRoot
|
|
STATIC s_lTest
|
|
|
|
STATIC s_hPackageList
|
|
|
|
PROCEDURE Main( ... )
|
|
|
|
s_cBase := ""
|
|
s_cHome := StrTran( hb_DirBase(), hb_ps(), "/" )
|
|
s_cRoot := s_cHome + "../"
|
|
|
|
s_lTest := "test" $ hb_cmdLine()
|
|
|
|
IF "migr" $ hb_cmdLine()
|
|
hb_setenv( "_HB_BUILD_MIGR", "yes" )
|
|
ENDIF
|
|
|
|
/* Load list of packages */
|
|
|
|
s_hPackageList := { => }
|
|
hb_HKeepOrder( s_hPackageList, .T. )
|
|
|
|
LoadPkgListFromFile( s_hPackageList, s_cHome + "pkglist" )
|
|
LoadPkgListFromString( s_hPackageList, GetEnv( "HB_BUILD_ADDONS" ) )
|
|
|
|
/* Build */
|
|
IF Empty( GetEnv( "HB_HOST_BIN_DIR" ) )
|
|
Standalone( ... )
|
|
ELSE
|
|
GNUMake( ... )
|
|
ENDIF
|
|
|
|
RETURN
|
|
|
|
/* Workflow translation for standalone operation:
|
|
|
|
GNU Make parameter nAction hbmk2 options
|
|
-- -------------- -------------- ---------------------- -------------------------
|
|
#1 clean clean _ACT_CLEAN -clean
|
|
#2 install install _ACT_INC_INST -inc -instpath=
|
|
#3 clean install clean install _ACT_INC_REBUILD_INST -inc -instpath= -rebuild
|
|
#4 _ACT_INC -inc
|
|
*/
|
|
PROCEDURE Standalone( ... )
|
|
LOCAL aParams
|
|
|
|
LOCAL aSortedList
|
|
|
|
LOCAL cPWD
|
|
LOCAL cBinDir
|
|
LOCAL cPackage
|
|
LOCAL cMyPackage
|
|
|
|
LOCAL cOptions
|
|
LOCAL cOptionsUser
|
|
|
|
LOCAL nAction
|
|
LOCAL tmp
|
|
LOCAL tmp1
|
|
|
|
LOCAL lCustom
|
|
|
|
LOCAL aPairList
|
|
|
|
/* Processing cmdline options */
|
|
|
|
aParams := hb_AParams()
|
|
|
|
DO CASE
|
|
CASE AScanL( aParams, "clean" ) > 0 .AND. ;
|
|
AScanL( aParams, "install" ) > 0 .AND. ;
|
|
AScanL( aParams, "install" ) > AScanL( aParams, "clean" )
|
|
nAction := _ACT_INC_REBUILD_INST
|
|
CASE AScanL( aParams, "clean" ) > 0
|
|
nAction := _ACT_CLEAN
|
|
CASE AScanL( aParams, "install" ) > 0
|
|
nAction := _ACT_INC_INST
|
|
OTHERWISE
|
|
nAction := _ACT_INC
|
|
ENDCASE
|
|
|
|
cOptionsUser := ""
|
|
lCustom := .F.
|
|
FOR EACH tmp IN aParams
|
|
IF !( Lower( tmp ) == "install" ) .AND. ;
|
|
!( Lower( tmp ) == "clean" ) .AND. ;
|
|
!( Lower( tmp ) == "all" ) .AND. ;
|
|
!( Lower( tmp ) == "first" )
|
|
|
|
cOptionsUser += " " + tmp
|
|
|
|
/* If anything else is passed than options or GNU Make keywords,
|
|
consider it a custom project build, f.e. in tests */
|
|
IF !( Left( tmp, 1 ) == "-" )
|
|
lCustom := .T.
|
|
ENDIF
|
|
ENDIF
|
|
NEXT
|
|
|
|
IF ! lCustom
|
|
cPWD := hb_pwd()
|
|
/* Find out which package are we */
|
|
FOR EACH tmp IN s_hPackageList
|
|
tmp1 := hb_ps() + PathSepToSelf( tmp:__enumKey() ) + hb_ps()
|
|
IF tmp1 == Right( cPWD, Len( tmp1 ) )
|
|
cMyPackage := StrTran( tmp:__enumKey(), "\", "/" )
|
|
EXIT
|
|
ENDIF
|
|
NEXT
|
|
IF Empty( cMyPackage )
|
|
lCustom := .T.
|
|
ELSE
|
|
OutStd( hb_StrFormat( "! Package '%1$s' %2$s...", cMyPackage, hActions[ nAction ] ) + hb_eol() )
|
|
ENDIF
|
|
ENDIF
|
|
|
|
cBinDir := s_cRoot + "bin" + hb_ps()
|
|
|
|
IF lCustom
|
|
mk_hb_processRun( PathSepToSelf( cBinDir ) + "hbmk2" + cOptionsUser )
|
|
ELSE
|
|
/* Converting build options to hbmk2 options */
|
|
|
|
cOptions := ""
|
|
|
|
IF nAction == _ACT_CLEAN
|
|
cOptions += " -clean"
|
|
ELSE
|
|
cOptions += " -inc"
|
|
IF nAction == _ACT_INC_REBUILD_INST
|
|
cOptions += " -rebuild"
|
|
ENDIF
|
|
ENDIF
|
|
|
|
/* Query project information and dependencies and calculate build order */
|
|
aPairList := {}
|
|
|
|
call_hbmk2_hbinfo( cBinDir, s_cBase + s_hPackageList[ cMyPackage ][ "cFileName" ], s_hPackageList[ cMyPackage ] )
|
|
DeptLinesToDeptPairList( aPairList, cMyPackage, s_hPackageList[ cMyPackage ][ "aDept" ] )
|
|
|
|
aSortedList := TopoSort( aPairList )
|
|
|
|
/* Build the dependencies and ourselves in in sorted order */
|
|
FOR EACH cPackage IN aSortedList DESCEND
|
|
call_hbmk2( cBinDir,;
|
|
s_cBase + iif( cPackage == cMyPackage, "", s_cHome + cPackage + "/" ) + s_hPackageList[ cPackage ][ "cFileName" ],;
|
|
iif( cPackage == cMyPackage, cOptions + cOptionsUser, " -inc" ), "" )
|
|
NEXT
|
|
ENDIF
|
|
|
|
ErrorLevel( 0 )
|
|
|
|
RETURN
|
|
|
|
/* Workflow translation from GNU Make to hbmk2:
|
|
|
|
GNU Make parameter HB_MAKECMDGOALS nAction hbmk2 options
|
|
-- -------------- ---------- ---------------- ---------------------- -------------------------
|
|
#1 clean clean clean _ACT_CLEAN -clean
|
|
#2 install install install _ACT_INC_INST -inc -instpath=
|
|
#3 clean install clean clean install _ACT_CLEAN -clean
|
|
install clean install _ACT_INC_REBUILD_INST -inc -instpath= -rebuild
|
|
#4 install clean install install clean _ACT_INC_INST -inc -instpath=
|
|
clean install clean _ACT_CLEAN -clean
|
|
#5 all _ACT_INC -inc
|
|
*/
|
|
PROCEDURE GNUMake( ... )
|
|
LOCAL cBinDir
|
|
LOCAL hProject
|
|
LOCAL cProject
|
|
LOCAL cPackage
|
|
|
|
LOCAL cOptions
|
|
|
|
LOCAL cFilter
|
|
LOCAL aFilter
|
|
LOCAL lFilterNegative
|
|
|
|
LOCAL aParams
|
|
LOCAL aGNUMakeParams
|
|
LOCAL nAction
|
|
|
|
LOCAL aPairList
|
|
|
|
LOCAL aSortedList
|
|
|
|
/* Check if the requirements are met and if we have anything to do */
|
|
|
|
IF Empty( GetEnv( "HB_PLATFORM" ) ) .OR. ;
|
|
Empty( GetEnv( "HB_COMPILER" ) ) .OR. ;
|
|
Empty( GetEnv( "HB_HOST_BIN_DIR" ) )
|
|
ErrorLevel( 9 )
|
|
RETURN
|
|
ENDIF
|
|
|
|
cFilter := GetEnv( "HB_BUILD_CONTRIBS" )
|
|
/* Compatibility */
|
|
IF Empty( cFilter )
|
|
cFilter := GetEnv( "HB_CONTRIBLIBS" )
|
|
ENDIF
|
|
|
|
IF ! Empty( cFilter )
|
|
OutStd( "! HB_BUILD_CONTRIBS: " + cFilter + hb_eol() )
|
|
ENDIF
|
|
|
|
IF cFilter == "no"
|
|
ErrorLevel( 0 )
|
|
RETURN
|
|
ENDIF
|
|
|
|
/* Determine the mode of operation */
|
|
|
|
aParams := hb_AParams()
|
|
aGNUMakeParams := hb_ATokens( Lower( GetEnv( "HB_MAKECMDGOALS" ) ) )
|
|
|
|
DO CASE
|
|
CASE AScanL( aParams, "clean" ) > 0
|
|
IF AScanL( aGNUMakeParams, "clean" ) > 0 .AND. ;
|
|
AScanL( aGNUMakeParams, "install" ) > 0 .AND. ;
|
|
AScanL( aGNUMakeParams, "install" ) > AScanL( aGNUMakeParams, "clean" )
|
|
nAction := _ACT_CLEAN
|
|
ELSE
|
|
nAction := _ACT_CLEAN
|
|
ENDIF
|
|
CASE AScanL( aParams, "install" ) > 0
|
|
IF AScanL( aGNUMakeParams, "clean" ) > 0 .AND. ;
|
|
AScanL( aGNUMakeParams, "install" ) > 0 .AND. ;
|
|
AScanL( aGNUMakeParams, "install" ) > AScanL( aGNUMakeParams, "clean" )
|
|
/* Use rebuild mode. This is needed because the clean phase
|
|
might not have been called previously by GNU Make, f.e.
|
|
because hbrun or hbmk2 wasn't available. -rebuild is
|
|
costless, so we do it to make sure to build cleanly.
|
|
[vszakats] */
|
|
nAction := _ACT_INC_REBUILD_INST
|
|
ELSE
|
|
nAction := _ACT_INC_INST
|
|
ENDIF
|
|
OTHERWISE
|
|
nAction := _ACT_INC
|
|
ENDCASE
|
|
|
|
/* Parse filter */
|
|
|
|
aFilter := iif( Empty( cFilter ), {}, hb_ATokens( cFilter,, .T. ) )
|
|
IF Len( aFilter ) >= 1 .AND. aFilter[ 1 ] == "no"
|
|
hb_ADel( aFilter, 1, .T. )
|
|
lFilterNegative := .T.
|
|
ELSE
|
|
lFilterNegative := .F.
|
|
ENDIF
|
|
|
|
/* Clearing envvars that may interact with hbmk2 */
|
|
|
|
/* Saving original install dirs to our own variables */
|
|
hb_setenv( "_HB_BIN_INSTALL", GetEnv( "HB_BIN_INSTALL" ) )
|
|
hb_setenv( "_HB_LIB_INSTALL", GetEnv( "HB_LIB_INSTALL" ) )
|
|
hb_setenv( "_HB_DYN_INSTALL", GetEnv( "HB_DYN_INSTALL" ) )
|
|
hb_setenv( "_HB_INC_INSTALL", GetEnv( "HB_INC_INSTALL" ) )
|
|
|
|
/* Override hbmk2 autodetection */
|
|
hb_setenv( "HB_INSTALL_PREFIX", s_cRoot )
|
|
hb_setenv( "HB_BIN_INSTALL", s_cRoot + "bin/" + GetEnv( "HB_PLATFORM" ) + "/" + GetEnv( "HB_COMPILER" ) + GetEnv( "HB_BUILD_NAME" ) )
|
|
hb_setenv( "HB_LIB_INSTALL", s_cRoot + "lib/" + GetEnv( "HB_PLATFORM" ) + "/" + GetEnv( "HB_COMPILER" ) + GetEnv( "HB_BUILD_NAME" ) )
|
|
hb_setenv( "HB_DYN_INSTALL" )
|
|
hb_setenv( "HB_INC_INSTALL", s_cRoot + "include" )
|
|
|
|
/* Preprocessing */
|
|
|
|
cBinDir := GetEnv( "HB_HOST_BIN_DIR" ) + hb_ps()
|
|
|
|
OutStd( "! Calculating build order for packages..." + hb_eol() )
|
|
|
|
aPairList := {}
|
|
|
|
FOR EACH hProject IN s_hPackageList
|
|
call_hbmk2_hbinfo( cBinDir, s_cBase + hProject:__enumKey() + "/" + hProject[ "cFileName" ], hProject )
|
|
DeptLinesToDeptPairList( aPairList, hProject:__enumKey(), hProject[ "aDept" ] )
|
|
NEXT
|
|
|
|
aSortedList := TopoSort( aPairList )
|
|
|
|
/* Converting build options to hbmk2 options */
|
|
|
|
hb_setenv( "_HB_BUILD_INSTALL" )
|
|
|
|
cOptions := ""
|
|
|
|
IF nAction == _ACT_CLEAN
|
|
cOptions += " -clean"
|
|
ELSE
|
|
cOptions += " -inc"
|
|
IF nAction == _ACT_INC_REBUILD_INST
|
|
cOptions += " -rebuild"
|
|
ENDIF
|
|
IF nAction == _ACT_INC_INST .OR. ;
|
|
nAction == _ACT_INC_REBUILD_INST
|
|
hb_setenv( "_HB_BUILD_INSTALL", "yes" )
|
|
ENDIF
|
|
ENDIF
|
|
|
|
/* Start building */
|
|
|
|
OutStd( hb_StrFormat( "! Started package %1$s...", hActions[ nAction ] ) + hb_eol() )
|
|
|
|
FOR EACH cPackage IN aSortedList DESCEND
|
|
|
|
IF Empty( aFilter ) .OR. ;
|
|
iif( lFilterNegative,;
|
|
AScan( aFilter, {| tmp | tmp == cPackage } ) == 0,;
|
|
AScan( aFilter, {| tmp | tmp == cPackage } ) > 0 )
|
|
|
|
cProject := s_cBase + cPackage + "/" + s_hPackageList[ cPackage ][ "cFileName" ]
|
|
|
|
call_hbmk2( cBinDir, cProject, cOptions, "" )
|
|
|
|
/* Highly experimental */
|
|
IF s_hPackageList[ cPackage ][ "cType" ] == "hblib" .AND. ;
|
|
GetEnv( "HB_BUILD_CONTRIB_DLL" ) == "yes" .AND. ;
|
|
hb_FileExists( PathSepToSelf( FNameExtSet( cProject, ".hbc" ) ) )
|
|
|
|
call_hbmk2( cBinDir, cProject, cOptions, " -hbdyn -nohblib- -implib " + FNameExtSet( cProject, ".hbc" ) )
|
|
ENDIF
|
|
|
|
/* Compile documentation */
|
|
IF nAction == _ACT_INC_INST .OR. ;
|
|
nAction == _ACT_INC_REBUILD_INST
|
|
mk_hbd( PathSepToSelf( cPackage ) )
|
|
ENDIF
|
|
ELSE
|
|
/* OutStd( hb_StrFormat( "! package '%1$s' skipped due to custom filter", cPackage ) + hb_eol() ) */
|
|
ENDIF
|
|
NEXT
|
|
|
|
OutStd( hb_eol() )
|
|
OutStd( hb_StrFormat( "! Finished package %1$s...", hActions[ nAction ] ) + hb_eol() )
|
|
|
|
ErrorLevel( 0 )
|
|
|
|
RETURN
|
|
|
|
STATIC PROCEDURE clear_hbmk2_envvars()
|
|
|
|
/* Making sure that user settings do not interfere with the std build process. */
|
|
hb_setenv( "HBMK_OPTIONS" )
|
|
hb_setenv( "HARBOUR" )
|
|
hb_setenv( "HARBOURCMD" )
|
|
hb_setenv( "CLIPPER" )
|
|
hb_setenv( "CLIPPERCMD" )
|
|
|
|
RETURN
|
|
|
|
STATIC FUNCTION call_hbmk2_hbinfo( cBinDir, cProject, hProject )
|
|
LOCAL cStdOut
|
|
LOCAL cDir
|
|
LOCAL cName
|
|
LOCAL tmp
|
|
|
|
hProject[ "cType" ] := ""
|
|
hProject[ "aDept" ] := {}
|
|
|
|
clear_hbmk2_envvars()
|
|
|
|
IF hb_processRun( PathSepToSelf( cBinDir ) + "hbmk2 --hbinfo " + StrTran( cProject, "\", "/" ),, @cStdOut ) == 0
|
|
|
|
hProject[ "cType" ] := hbmk2_hbinfo_getitem( cStdOut, "targettype" )
|
|
|
|
FOR EACH tmp IN hb_ATokens( hbmk2_hbinfo_getitem( cStdOut, "hbctree", .T. ), Chr( 10 ) )
|
|
IF ! Empty( tmp )
|
|
hb_FNameSplit( LTrim( tmp ), @cDir, @cName )
|
|
AAdd( hProject[ "aDept" ], { "nDepth" => Len( tmp ) - Len( LTrim( tmp ) ),;
|
|
"cDir" => cDir,;
|
|
"cName" => cName } )
|
|
ENDIF
|
|
NEXT
|
|
|
|
RETURN .T.
|
|
ENDIF
|
|
|
|
RETURN .F.
|
|
|
|
STATIC FUNCTION hbmk2_hbinfo_getitem( cString, cItem, lAll )
|
|
LOCAL cRetVal := ""
|
|
LOCAL nPos := 1
|
|
LOCAL tmp
|
|
|
|
DO WHILE ( tmp := hb_At( cItem + "{{", cString, nPos ) ) > 0
|
|
nPos := tmp + Len( cItem + "{{" )
|
|
IF ( tmp := hb_At( "}}", cString, nPos ) ) > 0
|
|
tmp := StrTran( SubStr( cString, nPos, tmp - nPos ), Chr( 13 ) )
|
|
IF lAll != NIL .AND. lAll
|
|
cRetVal += tmp
|
|
ELSE
|
|
/* Find the last occurrence, which is the root project */
|
|
cRetVal := tmp
|
|
ENDIF
|
|
ENDIF
|
|
ENDDO
|
|
|
|
RETURN cRetVal
|
|
|
|
STATIC FUNCTION call_hbmk2( cBinDir, cProject, cOptionsPre, cOptionsPost )
|
|
LOCAL nErrorLevel
|
|
|
|
clear_hbmk2_envvars()
|
|
|
|
nErrorLevel := mk_hb_processRun( PathSepToSelf( cBinDir ) + "hbmk2" +;
|
|
" -quiet -lang=en -width=0" +;
|
|
" @" + StrTran( s_cHome + "hbpre", "\", "/" ) +;
|
|
cOptionsPre +;
|
|
" " + StrTran( cProject, "\", "/" ) +;
|
|
" @" + StrTran( s_cHome, "\", "/" ) + "hbpost" +;
|
|
cOptionsPost )
|
|
|
|
IF nErrorLevel != 0
|
|
OutStd( hb_StrFormat( "! '%1$s' returned status: %2$s", cProject, hb_ntos( nErrorLevel ) ) + hb_eol() )
|
|
RETURN .F.
|
|
ENDIF
|
|
|
|
RETURN .T.
|
|
|
|
STATIC FUNCTION mk_hb_processRun( cCommand )
|
|
|
|
OutStd( cCommand + hb_eol() )
|
|
|
|
RETURN iif( s_lTest, 0, hb_processRun( cCommand ) )
|
|
|
|
STATIC FUNCTION mk_hbd( cDir )
|
|
LOCAL cName
|
|
LOCAL tmp
|
|
|
|
LOCAL aErrMsg
|
|
LOCAL aEntry
|
|
|
|
IF ! Empty( GetEnv( "HB_DOC_INSTALL" ) )
|
|
|
|
cName := DirGetName( cDir )
|
|
IF Empty( cName )
|
|
cName := "harbour"
|
|
ENDIF
|
|
|
|
aErrMsg := {}
|
|
aEntry := __hbdoc_LoadDir( cDir, cName, aErrMsg )
|
|
|
|
FOR EACH tmp IN aErrMsg
|
|
OutErr( hb_StrFormat( "! %1$s", tmp ) + hb_eol() )
|
|
NEXT
|
|
|
|
IF ! Empty( aEntry )
|
|
cName := PathSepToSelf( GetEnv( "HB_DOC_INSTALL" ) ) + hb_ps() + cName + ".hbd"
|
|
IF __hbdoc_SaveHBD( cName, aEntry )
|
|
OutStd( "! Compiled documentation: " + cName + " <= " + cDir + hb_eol() )
|
|
RETURN .T.
|
|
ELSE
|
|
OutErr( hb_StrFormat( "! Error: Saving '%1$s'", cName ) + hb_eol() )
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN .F.
|
|
|
|
STATIC FUNCTION AScanL( aArray, cString )
|
|
RETURN AScan( aArray, {| tmp | Lower( tmp ) == cString } )
|
|
|
|
STATIC FUNCTION FNameDirGet( cFileName )
|
|
LOCAL cDir
|
|
|
|
hb_FNameSplit( cFileName, @cDir )
|
|
|
|
RETURN cDir
|
|
|
|
STATIC FUNCTION FNameExtSet( cFileName, cExt )
|
|
LOCAL cDir, cName
|
|
|
|
hb_FNameSplit( cFileName, @cDir, @cName )
|
|
|
|
RETURN hb_FNameMerge( cDir, cName, cExt )
|
|
|
|
STATIC FUNCTION FNameExtDef( cFileName, cDefExt )
|
|
LOCAL cDir, cName, cExt
|
|
|
|
hb_FNameSplit( cFileName, @cDir, @cName, @cExt )
|
|
IF Empty( cExt )
|
|
cExt := cDefExt
|
|
ENDIF
|
|
|
|
RETURN hb_FNameMerge( cDir, cName, cExt )
|
|
|
|
STATIC FUNCTION DirGetName( cDir )
|
|
LOCAL cName
|
|
|
|
cDir := DirDelPathSep( cDir )
|
|
|
|
hb_FNameSplit( cDir,, @cName )
|
|
|
|
IF Empty( cName ) .OR. cName == "." .OR. cName == ".."
|
|
RETURN ""
|
|
ENDIF
|
|
|
|
RETURN cName
|
|
|
|
STATIC FUNCTION DirAddPathSep( cDir )
|
|
|
|
IF ! Empty( cDir ) .AND. !( Right( cDir, 1 ) == hb_ps() )
|
|
cDir += hb_ps()
|
|
ENDIF
|
|
|
|
RETURN cDir
|
|
|
|
STATIC FUNCTION DirDelPathSep( cDir )
|
|
|
|
IF Empty( hb_osDriveSeparator() )
|
|
DO WHILE Len( cDir ) > 1 .AND. Right( cDir, 1 ) == hb_ps()
|
|
cDir := hb_StrShrink( cDir, 1 )
|
|
ENDDO
|
|
ELSE
|
|
DO WHILE Len( cDir ) > 1 .AND. Right( cDir, 1 ) == hb_ps() .AND. ;
|
|
!( Right( cDir, 2 ) == hb_osDriveSeparator() + hb_ps() )
|
|
cDir := hb_StrShrink( cDir, 1 )
|
|
ENDDO
|
|
ENDIF
|
|
|
|
RETURN cDir
|
|
|
|
STATIC FUNCTION PathSepToSelf( cFileName )
|
|
RETURN StrTran( cFileName, iif( hb_ps() == "\", "/", "\" ), hb_ps() )
|
|
|
|
STATIC FUNCTION hb_pwd()
|
|
RETURN DirAddPathSep( hb_CurDrive() + hb_osDriveSeparator() + hb_ps() + CurDir() )
|
|
|
|
/* Convert indented list of line to tree / list of parent-child pairs */
|
|
STATIC PROCEDURE DeptLinesToDeptPairList( aPairList, cParent, aFlatTree )
|
|
LOCAL hFlatTreeElement
|
|
LOCAL hNode, hNewNode, tmp
|
|
LOCAL nLevel, nDepth
|
|
|
|
AddDeptPair( aPairList, "", cParent )
|
|
|
|
hNode := { "child" => {}, "name" => cParent, "parent" => NIL }
|
|
nLevel := 0
|
|
FOR EACH hFlatTreeElement IN aFlatTree
|
|
/* Min() protects against jumping more than one level down in one step */
|
|
nDepth := Min( hFlatTreeElement[ "nDepth" ], nLevel + 1 )
|
|
hNewNode := { "child" => {}, "name" => hFlatTreeElement[ "cName" ], "cargo" => hFlatTreeElement }
|
|
IF nDepth > nLevel
|
|
hNode := ATail( hNode[ "child" ] )
|
|
ELSEIF nDepth < nLevel
|
|
FOR tmp := nDepth + 1 TO nLevel
|
|
hNode := hNode[ "parent" ]
|
|
NEXT
|
|
ENDIF
|
|
hNewNode[ "parent" ] := hNode
|
|
AAdd( hNode[ "child" ], hNewNode )
|
|
nLevel := nDepth
|
|
AddDeptPair( aPairList, hNewNode[ "parent" ][ "name" ], hNewNode[ "name" ] )
|
|
NEXT
|
|
|
|
RETURN
|
|
|
|
/* Add parent-child dependency to the list */
|
|
STATIC PROCEDURE AddDeptPair( aPairList, cParent, cChild )
|
|
|
|
IF AScan( aPairList, {| tmp | tmp[ 1 ] == cParent .AND. tmp[ 2 ] == cChild } ) == 0
|
|
AAdd( aPairList, { cParent, cChild } )
|
|
ENDIF
|
|
|
|
RETURN
|
|
|
|
/* Topological sort of the dependency graph */
|
|
STATIC FUNCTION TopoSort( aEdgeList )
|
|
LOCAL aList := {}
|
|
LOCAL hTopNodes := { => }
|
|
|
|
LOCAL n, m
|
|
LOCAL tmp
|
|
|
|
hb_HKeepOrder( hTopNodes, .T. )
|
|
|
|
FOR EACH n IN aEdgeList
|
|
IF AScan( aEdgeList, {| tmp | tmp[ 2 ] == n[ 1 ] } ) == 0
|
|
hTopNodes[ n[ 1 ] ] := NIL
|
|
ENDIF
|
|
NEXT
|
|
|
|
DO WHILE ! Empty( hTopNodes )
|
|
n := hb_HKeyAt( hTopNodes, 1 )
|
|
hb_HDelAt( hTopNodes, 1 )
|
|
|
|
IF ! Empty( n )
|
|
AAdd( aList, n )
|
|
ENDIF
|
|
|
|
FOR EACH tmp IN aEdgeList
|
|
IF tmp[ 1 ] == n
|
|
m := tmp[ 2 ]
|
|
tmp[ 1 ] := tmp[ 2 ] := NIL /* set to invalid value. TOOPT: Delete this member from list */
|
|
IF AScan( aEdgeList, {| tmp | tmp[ 2 ] == m } ) == 0
|
|
hTopNodes[ m ] := NIL
|
|
ENDIF
|
|
ENDIF
|
|
NEXT
|
|
ENDDO
|
|
|
|
FOR EACH tmp IN aEdgeList
|
|
IF !( tmp[ 1 ] == NIL .AND. tmp[ 2 ] == NIL )
|
|
OutStd( hb_StrFormat( "! Warning: Circular reference in dependency tree (%1$s - %2$s)", tmp[ 1 ], tmp[ 2 ] ) + hb_eol() )
|
|
ENDIF
|
|
NEXT
|
|
|
|
RETURN aList
|
|
|
|
PROCEDURE AddPkg( hPackageList, cFileName )
|
|
LOCAL cDir
|
|
LOCAL cName
|
|
LOCAL cExt
|
|
|
|
IF ! Empty( cFileName )
|
|
|
|
hb_FNameSplit( PathSepToSelf( AllTrim( cFileName ) ), @cDir, @cName, @cExt )
|
|
IF ! Empty( cName ) .AND. Empty( cDir )
|
|
cDir := cName
|
|
ENDIF
|
|
IF Empty( cName )
|
|
cName := DirGetName( cDir )
|
|
ENDIF
|
|
IF Empty( cExt )
|
|
cExt := ".hbp"
|
|
ENDIF
|
|
|
|
hPackageList[ StrTran( DirDelPathSep( cDir ), "\", "/" ) ] := { "cFileName" => hb_FNameMerge(, cName, cExt ) }
|
|
ENDIF
|
|
|
|
RETURN
|
|
|
|
PROCEDURE LoadPkgListFromFile( hPackageList, cFileName )
|
|
LOCAL cFile := StrTran( MemoRead( cFileName ), Chr( 13 ) )
|
|
LOCAL cItem
|
|
|
|
FOR EACH cItem IN hb_ATokens( cFile, Chr( 10 ) )
|
|
IF "#" $ cItem
|
|
cItem := Left( cItem, At( "#", cItem ) - 1 )
|
|
ENDIF
|
|
AddPkg( hPackageList, cItem )
|
|
NEXT
|
|
|
|
RETURN
|
|
|
|
PROCEDURE LoadPkgListFromString( hPackageList, cString )
|
|
LOCAL cItem
|
|
|
|
FOR EACH cItem IN hb_ATokens( cString,, .T. )
|
|
AddPkg( hPackageList, cItem )
|
|
NEXT
|
|
|
|
RETURN
|