* debian/dirs
! Deleted doc/en dir.
* doc/Makefile
- doc/whatsnew.txt
+ NEWS
* COPYING
* doc/howtorel.txt
* debian/changelog
* package/mpkg_win.nsi
* package/winuni/mpkg_win_uni.bat
* package/winuni/mpkg_win_uni.nsi
* Renamed doc/whatsnew.txt to /NEWS
* debian/copyright
* Updated with COPYING content.
* package/harbour.spec
! Fixed to include doc/* instead of doc/*.txt.
* utils/hbrun/hbrun.prg
- Deleted envvar method of passing dirbase to scripts.
* contrib/make.hbs
+ Using HBRUN_DIRBASE() function instead of envvar trick.
Maybe some more generic named value passing would be better.
* contrib/Makefile
! Using '-' prefix when running hbrun instead of '+', to not
cause fatal breakage in build stage if make.hbs contains
something which previous build of hbrun didn't offer.
* config/global.mk
- HB_INSTALL_PREFIX will not default anymore to source root
dir (on non-*nix systems) to avoid FAQ where installation
fails because of former install into source root, causing
old contrib headers to ovveride current ones and breaking
build. Please note that 'install' is truly optional with
current builds, so only use it for what it was designed.
Pls should if some things fail with empty HB_INSTALL_PREFIX
and requesting 'install' anyway.
* contrib/xhb/xhbat.c
! Applied this fix to Harbour:
2010-07-29 12:28 UTC-0430 Ron Pinkas <ron.pinkas/at/xharbour.com>
* source/rtl/at.c
+ Added missing extended strings support, to hb_AtSkipStrings()
723 lines
21 KiB
Handlebars
Executable File
723 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. Move in external libs to contrib area? (bz2, minizip, sqlite3)
|
|
(the only downside is that irrelevant hits will be spilling
|
|
'grep -R' results)
|
|
4. 'install' is ignored in stdalone mode. It would be needed to
|
|
replicate the install dir defaulting logic found in global.mk
|
|
to implement it.
|
|
5. Delete header install related logic from GNU Make system,
|
|
also delete doc/*.txt install related logic (easily replacable
|
|
with postinst.hbs logic)
|
|
6. Honor paths found in --hbinfo hbctree{{}} section.
|
|
7. Move lib output dir and workdirs inside contrib dirs.
|
|
*/
|
|
|
|
#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_INC_CLEAN 1
|
|
#define _ACT_INC 2
|
|
#define _ACT_INC_INST 3
|
|
#define _ACT_INC_REBUILD 4
|
|
#define _ACT_INC_REBUILD_INST 5
|
|
|
|
STATIC hActions := {;
|
|
_ACT_INC_CLEAN => "clean" ,;
|
|
_ACT_INC => "build" ,;
|
|
_ACT_INC_INST => "build and install" ,;
|
|
_ACT_INC_REBUILD => "rebuild" ,;
|
|
_ACT_INC_REBUILD_INST => "rebuild and install" }
|
|
|
|
STATIC s_cBase
|
|
STATIC s_cHome
|
|
STATIC s_cRoot
|
|
STATIC s_cBinDir
|
|
|
|
PROCEDURE Main( ... )
|
|
LOCAL hPackageList
|
|
|
|
s_cBase := ""
|
|
s_cHome := StrTran( hb_DirBase(), hb_ps(), "/" )
|
|
s_cRoot := s_cHome + "../"
|
|
|
|
#if defined( __HBSCRIPT__HBRUN )
|
|
s_cBinDir := hbrun_DirBase()
|
|
#else
|
|
s_cBinDir := hb_DirBase()
|
|
#endif
|
|
|
|
/* Load list of packages */
|
|
|
|
hPackageList := { => }
|
|
hb_HKeepOrder( hPackageList, .T. )
|
|
|
|
LoadPkgListFromFile( hPackageList, s_cHome + "pkglist" )
|
|
LoadPkgListFromString( hPackageList, GetEnv( "HB_BUILD_ADDONS" ) )
|
|
|
|
/* Build */
|
|
IF Empty( GetEnv( "HB_HOST_BIN_DIR" ) )
|
|
Standalone( hb_AParams(), hPackageList )
|
|
ELSE
|
|
GNUMake( hb_AParams(), hPackageList )
|
|
ENDIF
|
|
|
|
RETURN
|
|
|
|
/* Workflow translation for standalone operation:
|
|
|
|
GNU Make parameter nAction hbmk2 options
|
|
-- -------------- -------------- ---------------------- -------------------------
|
|
#1 clean clean _ACT_INC_CLEAN -inc -clean
|
|
#2 _ACT_INC -inc
|
|
#3 clean all clean all _ACT_INC_REBUILD -inc -rebuild
|
|
#4 install install _ACT_INC_INST -inc -instpath=
|
|
#5 clean install clean install _ACT_INC_REBUILD_INST -inc -rebuild -instpath=
|
|
*/
|
|
PROCEDURE Standalone( aParams, hPackageList )
|
|
LOCAL aSortedList
|
|
|
|
LOCAL cPWD
|
|
LOCAL cPackage
|
|
LOCAL cMyPackage
|
|
|
|
LOCAL cOptions
|
|
LOCAL cOptionsUser
|
|
|
|
LOCAL nAction
|
|
LOCAL tmp
|
|
LOCAL tmp1
|
|
|
|
LOCAL lCustom
|
|
|
|
LOCAL aPairList
|
|
|
|
/* Processing cmdline options */
|
|
|
|
DO CASE
|
|
CASE AScanL( aParams, "clean" ) > 0 .AND. ;
|
|
AScanL( aParams, "all" ) > 0 .AND. ;
|
|
AScanL( aParams, "all" ) > AScanL( aParams, "clean" )
|
|
nAction := _ACT_INC_REBUILD
|
|
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_INC_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 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
|
|
|
|
IF lCustom
|
|
mk_hb_processRun( s_cBinDir + "hbmk2" + cOptionsUser )
|
|
ELSE
|
|
/* Converting build options to hbmk2 options */
|
|
|
|
cOptions := " -inc"
|
|
IF nAction == _ACT_INC_CLEAN
|
|
cOptions += " -clean"
|
|
ELSE
|
|
IF nAction == _ACT_INC_REBUILD .OR. ;
|
|
nAction == _ACT_INC_REBUILD_INST
|
|
cOptions += " -rebuild"
|
|
ENDIF
|
|
ENDIF
|
|
|
|
/* Query project information and dependencies and calculate build order */
|
|
aPairList := {}
|
|
|
|
call_hbmk2_hbinfo( s_cBase + hPackageList[ cMyPackage ][ "cFileName" ], hPackageList[ cMyPackage ] )
|
|
DeptLinesToDeptPairList( aPairList, cMyPackage, hPackageList[ cMyPackage ][ "aDept" ] )
|
|
|
|
aSortedList := TopoSort( aPairList )
|
|
|
|
/* Build the dependencies and ourselves in in sorted order */
|
|
FOR EACH cPackage IN aSortedList DESCEND
|
|
call_hbmk2( s_cBase + iif( cPackage == cMyPackage, "", s_cHome + cPackage + "/" ) + 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_INC_CLEAN -inc -clean
|
|
#2 all _ACT_INC -inc
|
|
#3 install install install _ACT_INC_INST -inc -instpath=
|
|
#4 clean all clean clean all _ACT_INC_CLEAN -inc -clean
|
|
first clean all _ACT_INC_REBUILD -inc -rebuild
|
|
#5 clean install clean clean install _ACT_INC_CLEAN -inc -clean
|
|
install clean install _ACT_INC_REBUILD_INST -inc -rebuild -instpath=
|
|
#6 install clean install install clean _ACT_INC_INST -inc -instpath=
|
|
clean install clean _ACT_INC_CLEAN -inc -clean
|
|
*/
|
|
PROCEDURE GNUMake( aParams, hPackageList )
|
|
LOCAL hProject
|
|
LOCAL cProject
|
|
LOCAL cPackage
|
|
|
|
LOCAL cOptions
|
|
|
|
LOCAL cFilter
|
|
LOCAL aFilter
|
|
LOCAL lFilterNegative
|
|
|
|
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 */
|
|
|
|
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_INC_CLEAN
|
|
ELSE
|
|
nAction := _ACT_INC_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
|
|
CASE AScanL( aParams, "first" ) > 0
|
|
IF AScanL( aGNUMakeParams, "clean" ) > 0 .AND. ;
|
|
AScanL( aGNUMakeParams, "all" ) > 0 .AND. ;
|
|
AScanL( aGNUMakeParams, "all" ) > AScanL( aGNUMakeParams, "clean" )
|
|
nAction := _ACT_INC_REBUILD
|
|
ELSE
|
|
nAction := _ACT_INC
|
|
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_INSTALL_BIN", GetEnv( "HB_INSTALL_BIN" ) )
|
|
hb_setenv( "_HB_INSTALL_LIB", GetEnv( "HB_INSTALL_LIB" ) )
|
|
hb_setenv( "_HB_INSTALL_DYN", GetEnv( "HB_INSTALL_DYN" ) )
|
|
hb_setenv( "_HB_INSTALL_INC", GetEnv( "HB_INSTALL_INC" ) )
|
|
hb_setenv( "_HB_INSTALL_MAN", GetEnv( "HB_INSTALL_MAN" ) )
|
|
hb_setenv( "_HB_INSTALL_ETC", GetEnv( "HB_INSTALL_ETC" ) )
|
|
|
|
/* Override hbmk2 autodetection */
|
|
hb_setenv( "HB_INSTALL_PREFIX", s_cRoot )
|
|
hb_setenv( "HB_INSTALL_BIN", s_cRoot + "bin/" + GetEnv( "HB_PLATFORM" ) + "/" + GetEnv( "HB_COMPILER" ) + GetEnv( "HB_BUILD_NAME" ) )
|
|
hb_setenv( "HB_INSTALL_LIB", s_cRoot + "lib/" + GetEnv( "HB_PLATFORM" ) + "/" + GetEnv( "HB_COMPILER" ) + GetEnv( "HB_BUILD_NAME" ) )
|
|
hb_setenv( "HB_INSTALL_DYN" )
|
|
hb_setenv( "HB_INSTALL_INC", s_cRoot + "include" )
|
|
|
|
/* Preprocessing */
|
|
|
|
OutStd( "! Calculating build order for packages..." + hb_eol() )
|
|
|
|
aPairList := {}
|
|
|
|
FOR EACH hProject IN hPackageList
|
|
call_hbmk2_hbinfo( 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 := " -inc"
|
|
IF nAction == _ACT_INC_CLEAN
|
|
cOptions += " -clean"
|
|
ELSE
|
|
IF nAction == _ACT_INC_REBUILD .OR. ;
|
|
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 + "/" + hPackageList[ cPackage ][ "cFileName" ]
|
|
|
|
call_hbmk2( cProject, cOptions, "" )
|
|
|
|
/* Highly experimental */
|
|
IF hPackageList[ cPackage ][ "cType" ] == "hblib" .AND. ;
|
|
GetEnv( "HB_BUILD_CONTRIB_DLL" ) == "yes" .AND. ;
|
|
hb_FileExists( PathSepToSelf( FNameExtSet( cProject, ".hbc" ) ) )
|
|
|
|
call_hbmk2( 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( cProject, hProject )
|
|
LOCAL cStdOut
|
|
LOCAL cDir
|
|
LOCAL cName
|
|
LOCAL tmp
|
|
|
|
hProject[ "cType" ] := ""
|
|
hProject[ "aDept" ] := {}
|
|
|
|
clear_hbmk2_envvars()
|
|
|
|
IF hb_processRun( s_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( cProject, cOptionsPre, cOptionsPost )
|
|
LOCAL nErrorLevel
|
|
|
|
clear_hbmk2_envvars()
|
|
|
|
nErrorLevel := mk_hb_processRun( s_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 hb_processRun( cCommand )
|
|
|
|
STATIC FUNCTION mk_hbd( cDir )
|
|
LOCAL cName
|
|
LOCAL tmp
|
|
|
|
LOCAL aErrMsg
|
|
LOCAL aEntry
|
|
|
|
IF ! Empty( GetEnv( "HB_INSTALL_DOC" ) )
|
|
|
|
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_INSTALL_DOC" ) ) + 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
|