* utils/hbrun/hbrun.prg
! Don't search passed program in PATH and hbrun dir, if
program name has path component.
* contrib/xhb/xhbenum.c
* contrib/xhb/xhbqself.c
* contrib/xhb/xhbwith.c
* contrib/xhb/xhberrc.c
! Fixed msvc64 warnings after HB_SIZE extension in stack API.
* contrib/make.hbs
+ Added logic to protect against case when 'clean install'
is used but hbrun or hbmk2 isn't available when launching
the make process. In this case 'clean' phase won't be executed
for contribs, which is solved by forcing a -rebuild in
'install' phase.
* src/vm/strapi.c
* src/vm/runner.c
* src/vm/itemapi.c
* src/vm/asort.c
* src/vm/hvm.c
* src/vm/arrays.c
* src/vm/memvars.c
* src/vm/set.c
* src/vm/classes.c
* src/rtl/lennum.c
* src/rtl/strcase.c
* src/rtl/replic.c
* src/rtl/padr.c
* src/rtl/padc.c
* src/rtl/strtran.c
* src/rtl/strtoexp.c
* src/rtl/padl.c
* src/rtl/saverest.c
* src/rtl/right.c
* src/rtl/philes.c
* src/rtl/mlcfunc.c
* src/rtl/left.c
* src/rtl/xsavescr.c
* src/rtl/setkey.c
* src/rtl/stuff.c
* src/rtl/trace.c
* src/rtl/samples.c
* src/rtl/inkeyapi.c
* src/rtl/inkey.c
* src/rtl/mtran.c
* src/rtl/colorind.c
* src/rtl/rat.c
* include/hbapi.h
* include/hbapistr.h
* Renamed HB_SIZE variables to have 'n' prefix.
(verified to generate the same objects as before)
* src/rtl/philes.c
* Changed hb_retnint()/hb_retni() to hb_retns().
* contrib/hbgd/gdwrp.c
* Formatting.
443 lines
15 KiB
Handlebars
443 lines
15 KiB
Handlebars
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* This Harbour script is part of the GNU Make-based build system.
|
|
* WARNING: Running it separately is not supported.
|
|
*
|
|
* Copyright 2010 Viktor Szakats (harbour.01 syenar.hu)
|
|
* See COPYING for licensing terms.
|
|
*/
|
|
|
|
/* TODO:
|
|
1. error handling / reporting / feedback
|
|
2. solve the automatic in-dir make clean/install/rebuild workflow
|
|
*/
|
|
|
|
/* #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_EXIT 0
|
|
#define _ACT_CLEAN 1
|
|
#define _ACT_INC 2
|
|
#define _ACT_INC_INST 3
|
|
#define _ACT_INC_REBUILD_INST 4
|
|
|
|
STATIC s_lStdAlone
|
|
STATIC s_lTest
|
|
STATIC s_lMigr
|
|
|
|
PROCEDURE Main( ... )
|
|
|
|
LOCAL cBase := ""
|
|
LOCAL cRoot := "../"
|
|
|
|
LOCAL aImpLibs := {;
|
|
"gtalleg/gtalleg.hbi" ,;
|
|
"hbblat/hbblat.hbi" ,;
|
|
"hbcairo/hbcairo.hbi" ,;
|
|
"hbcurl/hbcurl.hbi" ,;
|
|
"hbfbird/hbfbird.hbi" ,;
|
|
"hbfimage/hbfimage.hbi" ,;
|
|
"hbgd/hbgd.hbi" ,;
|
|
"hbhpdf/hbhpdf.hbi" ,;
|
|
"hbmysql/hbmysql.hbi" ,;
|
|
"hbpgsql/hbpgsql.hbi" ,;
|
|
"hbssl/hbssl.hbi" ,;
|
|
"rddads/rddads.hbi" ,;
|
|
"sddfb/sddfb.hbi" ,;
|
|
"sddmy/sddmy.hbi" ,;
|
|
"sddoci/sddoci.hbi" ,;
|
|
"sddpg/sddpg.hbi" }
|
|
|
|
/* external libs hosted locally */
|
|
LOCAL aLibsPass0 := {}
|
|
|
|
LOCAL aLibsPass1 := {;
|
|
"hbblink/hbblink.hbp" ,;
|
|
"hbbz2/hbbz2.hbp" ,; /* uses: bz2 (external) */
|
|
"hbclipsm/hbclipsm.hbp" ,;
|
|
"hbcomm/hbcomm.hbp" ,;
|
|
"hbct/hbct.hbp" ,;
|
|
"hbfoxpro/hbfoxpro.hbp" ,;
|
|
"hbfship/hbfship.hbp" ,;
|
|
"hbgt/hbgt.hbp" ,;
|
|
"hbmemio/hbmemio.hbp" ,;
|
|
"hbmisc/hbmisc.hbp" ,;
|
|
"hbmzip/hbmzip.hbp" ,; /* uses: minizip (external) */
|
|
"hbnetio/hbnetio.hbp" ,;
|
|
"hbnf/hbnf.hbp" ,;
|
|
"hbodbc/hbodbc.hbp" ,;
|
|
"hbsms/hbsms.hbp" ,;
|
|
"hbsqlit3/hbsqlit3.hbp" ,; /* uses: sqlite3 (external) */
|
|
"hbtpathy/hbtpathy.hbp" ,;
|
|
"hbwin/hbwin.hbp" ,;
|
|
"hbxpp/hbxpp.hbp" ,;
|
|
"rddbmcdx/hbbmcdx.hbp" }
|
|
|
|
LOCAL aLibsPass2 := {;
|
|
"gtalleg/gtalleg.hbp" ,;
|
|
"gtalleg/gtallegs.hbp" ,;
|
|
"hbblat/hbblat.hbp" ,;
|
|
"hbcairo/hbcairo.hbp" ,;
|
|
"hbcups/hbcups.hbp" ,;
|
|
"hbcurl/hbcurl.hbp" ,;
|
|
"hbcurl/hbcurls.hbp" ,;
|
|
"hbfbird/hbfbird.hbp" ,;
|
|
"hbfimage/hbfimage.hbp" ,;
|
|
"hbgd/hbgd.hbp" ,; /* uses: hbct */
|
|
"hbhpdf/hbhpdf.hbp" ,;
|
|
"hbmysql/hbmysql.hbp" ,;
|
|
"hbpgsql/hbpgsql.hbp" ,;
|
|
"hbqt/hbqt.hbp" ,;
|
|
"hbqt/hbqtcore.hbp" ,;
|
|
"hbqt/hbqtcores.hbp" ,;
|
|
"hbqt/hbqtgui.hbp" ,;
|
|
"hbqt/hbqtguis.hbp" ,;
|
|
"hbqt/hbqtnetwork.hbp" ,;
|
|
"hbqt/hbqtnetworks.hbp" ,;
|
|
"hbqt/hbqts.hbp" ,;
|
|
"hbssl/hbssl.hbp" ,;
|
|
"hbssl/hbssls.hbp" ,;
|
|
"hbxbp/hbxbp.hbp" ,; /* uses: hbqt */
|
|
"rddads/rddads.hbp" ,;
|
|
"rddsql/rddsql.hbp" ,;
|
|
"sddfb/sddfb.hbp" ,; /* uses: rddsql */
|
|
"sddmy/sddmy.hbp" ,; /* uses: rddsql */
|
|
"sddoci/sddoci.hbp" ,; /* uses: rddsql */
|
|
"sddodbc/sddodbc.hbp" ,; /* uses: rddsql */
|
|
"sddpg/sddpg.hbp" ,; /* uses: rddsql */
|
|
"sddsqlt3/sddsqlt3.hbp" } /* uses: rddsql, sqlite3 (external) */
|
|
|
|
LOCAL aLibsPass3 := {;
|
|
"gtwvg/gtwvg.hbp" ,; /* uses: hbwin */
|
|
"hbtip/hbtip.hbp" ,;
|
|
"hbtip/hbtipssl.hbp" ,; /* uses: hbssl */
|
|
"hbziparc/hbziparc.hbp" ,; /* uses: hbmzip */
|
|
"xhb/xhb.hbp" } /* uses: hbct, hbtip, hbwin */
|
|
|
|
LOCAL aUtils := {;
|
|
"hbnetio/utils/hbnetio.hbp" ,; /* uses: hbnetio */
|
|
"hbide/hbide.hbp" } /* uses: hbxbp, hbqt */
|
|
|
|
LOCAL aAll
|
|
LOCAL hItem
|
|
|
|
LOCAL cProject
|
|
LOCAL cProjectDir
|
|
LOCAL cInstallDirVar
|
|
LOCAL cTargetDir
|
|
|
|
LOCAL cBaseOptions
|
|
LOCAL cOptionsPre
|
|
LOCAL cOptionsPost
|
|
LOCAL lBuildName
|
|
|
|
LOCAL cFilter
|
|
LOCAL aFilter
|
|
LOCAL lFilterNegative
|
|
|
|
LOCAL aParams
|
|
LOCAL aGNUMakeParams
|
|
LOCAL tmp
|
|
LOCAL nAction
|
|
|
|
s_lStdAlone := Empty( "HB_HOST_BIN_DIR" )
|
|
s_lMigr := "migr" $ hb_cmdLine()
|
|
|
|
IF s_lMigr
|
|
OutStd( "! New contrib make orchestrator test run. |" + hb_cmdLine() + "|" + GetEnv( "HB_MAKECMDGOALS" ) + "|" + hb_dirBase() + "|" + CurDir() + "|", hb_eol() )
|
|
|
|
/* testing with a limited set of contribs */
|
|
aLibsPass1 := {;
|
|
"hbblat/hbblat.hbp" ,;
|
|
"hbblink/hbblink.hbp" ,;
|
|
"hbclipsm/hbclipsm.hbp" ,;
|
|
"hbnetio/hbnetio.hbp" ,;
|
|
"rddbmcdx/hbbmcdx.hbp" }
|
|
aLibsPass2 := {}
|
|
aLibsPass3 := {}
|
|
aUtils := {;
|
|
"hbnetio/utils/hbnetio.hbp" }
|
|
ENDIF
|
|
|
|
/*
|
|
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
|
|
|
|
*/
|
|
|
|
/* Determine the mode of operation */
|
|
|
|
s_lTest := "test" $ hb_cmdLine()
|
|
|
|
aParams := hb_AParams()
|
|
aGNUMakeParams := hb_ATokens( Lower( GetEnv( "HB_MAKECMDGOALS" ) ) )
|
|
|
|
DO CASE
|
|
CASE AScan( aParams, "clean" ) > 0
|
|
IF AScan( aGNUMakeParams, "clean" ) > 0 .AND. ;
|
|
AScan( aGNUMakeParams, "install" ) > 0 .AND. ;
|
|
AScan( aGNUMakeParams, "install" ) > AScan( aGNUMakeParams, "clean" )
|
|
nAction := _ACT_CLEAN
|
|
ELSE
|
|
nAction := _ACT_CLEAN
|
|
ENDIF
|
|
CASE AScan( aParams, "install" ) > 0
|
|
IF AScan( aGNUMakeParams, "clean" ) > 0 .AND. ;
|
|
AScan( aGNUMakeParams, "install" ) > 0 .AND. ;
|
|
AScan( aGNUMakeParams, "install" ) > AScan( 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
|
|
|
|
IF nAction == _ACT_EXIT
|
|
ErrorLevel( 0 )
|
|
RETURN
|
|
ENDIF
|
|
|
|
/* 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_CONTRIBLIBS" )
|
|
|
|
IF cFilter == "no"
|
|
ErrorLevel( 0 )
|
|
RETURN
|
|
ENDIF
|
|
|
|
SetCancel( .F. )
|
|
|
|
/* Converting build options to hbmk2 options */
|
|
|
|
cBaseOptions := "-quiet -lang=en -width=0 -q0"
|
|
IF s_lMigr
|
|
cBaseOptions += " -quiet- -info -trace"
|
|
ENDIF
|
|
|
|
IF GetEnv( "HB_BUILD_MODE" ) == "cpp"
|
|
cBaseOptions += " -cpp=yes"
|
|
ELSEIF GetEnv( "HB_BUILD_MODE" ) == "c"
|
|
cBaseOptions += " -cpp=no"
|
|
ENDIF
|
|
IF GetEnv( "HB_BUILD_DEBUG" ) == "yes"
|
|
cBaseOptions += " -debug"
|
|
ENDIF
|
|
IF ! Empty( GetEnv( "HB_BUILD_NAME" ) )
|
|
cBaseOptions += " -build=" + GetEnv( "HB_BUILD_NAME" )
|
|
lBuildName := .T.
|
|
ELSE
|
|
lBuildName := .F.
|
|
ENDIF
|
|
|
|
/* Clearing envvars that may interact with hbmk2 */
|
|
|
|
/* Copy 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", cRoot )
|
|
hb_setenv( "HB_BIN_INSTALL", cRoot + "bin/" + GetEnv( "HB_PLATFORM" ) + "/" + GetEnv( "HB_COMPILER" ) + iif( lBuildName, "/" + GetEnv( "HB_BUILD_NAME" ), "" ) )
|
|
hb_setenv( "HB_LIB_INSTALL", cRoot + "lib/" + GetEnv( "HB_PLATFORM" ) + "/" + GetEnv( "HB_COMPILER" ) + iif( lBuildName, "/" + GetEnv( "HB_BUILD_NAME" ), "" ) )
|
|
hb_setenv( "HB_DYN_INSTALL" )
|
|
hb_setenv( "HB_INC_INSTALL", cRoot + "include" )
|
|
|
|
/* Using shorter vars to save on cmdline length */
|
|
hb_setenv( "__HB_B", GetEnv( "HB_BIN_INSTALL" ) )
|
|
hb_setenv( "__HB_L", GetEnv( "HB_LIB_INSTALL" ) )
|
|
hb_setenv( "__HB_D", GetEnv( "HB_DYN_INSTALL" ) )
|
|
hb_setenv( "__HB_I", GetEnv( "HB_INC_INSTALL" ) )
|
|
|
|
/* 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
|
|
|
|
/* Start building */
|
|
|
|
aAll := {;
|
|
{ "type" => "implib", "list" => aImpLibs },;
|
|
{ "type" => "lib" , "list" => aLibsPass0 },;
|
|
{ "type" => "lib" , "list" => aLibsPass1 },;
|
|
{ "type" => "lib" , "list" => aLibsPass2 },;
|
|
{ "type" => "lib" , "list" => aLibsPass3 },;
|
|
{ "type" => "bin" , "list" => aUtils },;
|
|
{ "type" => "lib" , "list" => hb_ATokens( GetEnv( "HB_ADDONS_LIB" ),, .T. ) },;
|
|
{ "type" => "bin" , "list" => hb_ATokens( GetEnv( "HB_ADDONS_BIN" ),, .T. ) } }
|
|
|
|
FOR EACH hItem IN aAll
|
|
FOR EACH cProject IN hItem[ "list" ]
|
|
|
|
IF ! Empty( cProject )
|
|
|
|
cProject := StrTran( cProject, "\", "/" )
|
|
|
|
IF ( tmp := At( "/", cProject ) ) > 0
|
|
cProjectDir := Left( cProject, tmp - 1 )
|
|
ELSE
|
|
cProjectDir := ""
|
|
ENDIF
|
|
|
|
IF Empty( aFilter ) .OR. ;
|
|
iif( lFilterNegative,;
|
|
AScan( aFilter, {| tmp | tmp == cProjectDir } ) == 0,;
|
|
AScan( aFilter, {| tmp | tmp == cProjectDir } ) > 0 )
|
|
|
|
cOptionsPre := cBaseOptions
|
|
cOptionsPost := ""
|
|
|
|
SWITCH hItem[ "type" ]
|
|
CASE "lib"
|
|
CASE "implib"
|
|
cTargetDir := "${__HB_L}"
|
|
cInstallDirVar := "_HB_LIB_INSTALL"
|
|
EXIT
|
|
CASE "bin"
|
|
cTargetDir := "${__HB_B}"
|
|
cInstallDirVar := "_HB_BIN_INSTALL"
|
|
IF GetEnv( "HB_BUILD_SHARED" ) == "yes"
|
|
cOptionsPre += " -shared"
|
|
ENDIF
|
|
EXIT
|
|
ENDSWITCH
|
|
|
|
IF nAction == _ACT_CLEAN
|
|
cOptionsPre += " -clean"
|
|
ELSE
|
|
cOptionsPre += " -inc"
|
|
IF nAction == _ACT_INC_REBUILD_INST
|
|
cOptionsPre += " -rebuild"
|
|
ENDIF
|
|
IF nAction == _ACT_INC_INST .OR. ;
|
|
nAction == _ACT_INC_REBUILD_INST
|
|
IF ! Empty( GetEnv( cInstallDirVar ) ) .AND. ;
|
|
( ! ( hItem[ "type" ] == "implib" ) .OR. GetEnv( "HB_BUILD_IMPLIB" ) == "yes" )
|
|
cOptionsPre += " -instpath=${" + cInstallDirVar + "}/"
|
|
IF hItem[ "type" ] == "lib"
|
|
cOptionsPre += " -instpath=inc:${_HB_INC_INSTALL}/"
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
call_hbmk2( cBase + cProject, cTargetDir, cOptionsPre, cOptionsPost, .F. )
|
|
|
|
/* Highly experimental */
|
|
IF hItem[ "type" ] == "lib" .AND. GetEnv( "HB_BUILD_CONTRIB_DLL" ) == "yes" .AND. ;
|
|
hb_FileExists( FN_ExtSet( cBase + cProject, ".hbc" ) )
|
|
|
|
cInstallDirVar := "_HB_DYN_INSTALL"
|
|
|
|
cOptionsPre := cBaseOptions
|
|
/* TOFIX: Add -implib option. It collides with static lib so needs to be resolved. */
|
|
cOptionsPost := " -hbdyn -nohblib- " + FN_ExtSet( cProject, ".hbc" )
|
|
|
|
IF nAction == _ACT_CLEAN
|
|
cOptionsPre += " -clean"
|
|
ELSE
|
|
cOptionsPre += " -inc"
|
|
IF nAction == _ACT_INC_REBUILD_INST
|
|
cOptionsPre += " -rebuild"
|
|
ENDIF
|
|
IF nAction == _ACT_INC_INST .OR. ;
|
|
nAction == _ACT_INC_REBUILD_INST
|
|
IF ! Empty( GetEnv( cInstallDirVar ) )
|
|
cOptionsPre += " -instpath=${" + cInstallDirVar + "}/"
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
call_hbmk2( cBase + cProject, cTargetDir, cOptionsPre, cOptionsPost, .T. )
|
|
ENDIF
|
|
ELSE
|
|
/* OutStd( hb_StrFormat( "'%s' project skipped", cProject ), hb_eol() ) */
|
|
ENDIF
|
|
ENDIF
|
|
NEXT
|
|
NEXT
|
|
|
|
ErrorLevel( 0 )
|
|
|
|
RETURN
|
|
|
|
STATIC FUNCTION call_hbmk2( cProject, cTargetDir, cOptionsPre, cOptionsPost, lDyn )
|
|
LOCAL nErrorLevel
|
|
|
|
LOCAL cDir, cName
|
|
|
|
hb_FNameSplit( cProject, @cDir, @cName )
|
|
|
|
/* Keeping cmdline as short as possible. Also making sure that user settings
|
|
do not interfere with the std build process. */
|
|
hb_setenv( "HBMK_OPTIONS", cOptionsPre )
|
|
|
|
nErrorLevel := mk_hb_processRun( PathSepToSelf( GetEnv( "HB_HOST_BIN_DIR" ) ) + hb_ps() + "hbmk2" +;
|
|
" " + cProject +;
|
|
cOptionsPost +;
|
|
" -workdir=" + cTargetDir + "/${hb_work}/" + cName + iif( lDyn, "${hb_workdynsub}", "" ) +;
|
|
" -o" + cTargetDir + "/" )
|
|
IF nErrorLevel != 0
|
|
OutStd( hb_StrFormat( "'%s' returned status: %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 FN_ExtSet( cFileName, cExt )
|
|
LOCAL cDir, cName
|
|
|
|
hb_FNameSplit( cFileName, @cDir, @cName )
|
|
|
|
RETURN hb_FNameMerge( cDir, cName, cExt )
|
|
|
|
STATIC FUNCTION PathSepToSelf( cFileName )
|
|
#if defined( __PLATFORM__WINDOWS ) .OR. ;
|
|
defined( __PLATFORM__DOS ) .OR. ;
|
|
defined( __PLATFORM__OS2 )
|
|
RETURN StrTran( cFileName, "/", "\" )
|
|
#else
|
|
RETURN StrTran( cFileName, "\", "/" )
|
|
#endif
|