diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 0de4a5bd54..893f4c6f8a 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,20 @@ 2009-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2009-02-14 13:17 UTC+0100 Viktor Szakats (harbour.01 syenar hu) + * make_b32.mak + * make_vc.mak + * make_gcc.mak + * common.mak + * utils/Makefile + + Added hbmk to make systems. + + * utils/hbmk/hbmk.prg + + Update. Second pass, it's now ready for testing. I've + only tried with BCC yet. + Please test and if possible update internal setup + for various platforms/compilers. + 2009-02-14 10:49 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/source/vm/memvars.c % small optimization in __MVSAVE() diff --git a/harbour/common.mak b/harbour/common.mak index 5f8d7be0e7..2b460f3985 100644 --- a/harbour/common.mak +++ b/harbour/common.mak @@ -169,6 +169,7 @@ HBTEST_DIR = utils\hbtest HBI18N_DIR = utils\hbi18n HBDOC_DIR = utils\hbdoc HBMAKE_DIR = utils\hbmake +HBMK_DIR = utils\hbmk #********************************************************** @@ -216,7 +217,8 @@ $(HBRUN_DIR);\ $(HBTEST_DIR);\ $(HBI18N_DIR);\ $(HBDOC_DIR);\ -$(HBMAKE_DIR)\ +$(HBMAKE_DIR);\ +$(HBMK_DIR)\ ALL_SRC_DIRS_TMP=\ $(ALL_LIB_SRC_DIRS_TMP);\ @@ -283,6 +285,7 @@ HBTEST_EXE = $(BIN_DIR)\hbtest$(EXEEXT) HBI18N_EXE = $(BIN_DIR)\hbi18n$(EXEEXT) HBDOC_EXE = $(BIN_DIR)\hbdoc$(EXEEXT) HBMAKE_EXE = $(BIN_DIR)\hbmake$(EXEEXT) +HBMK_EXE = $(BIN_DIR)\hbmk$(EXEEXT) HB_DLLVER = 11 HARBOUR_DLL = $(BIN_DIR)\$(LIBPREF)harbour-$(HB_DLLVER)-$(HB_CC_NAME)$(DLLEXT) @@ -1209,6 +1212,11 @@ HBMAKE_EXE_OBJS = \ $(OBJ_DIR)\hbmfrdln$(OBJEXT) \ $(OBJ_DIR)\hbmlang$(OBJEXT) \ +#********************************************************** + +HBMK_EXE_OBJS = \ + $(OBJ_DIR)\hbmk$(OBJEXT) \ + #********************************************************** #********************************************************** #********************************************************** @@ -1310,6 +1318,7 @@ HB_BUILD_TARGETS_MAIN = \ $(HBI18N_EXE) \ $(HBDOC_EXE) \ $(HBMAKE_EXE) \ + $(HBMK_EXE) \ # DLL Target is disabled by default # It can be enabled by setting env diff --git a/harbour/make_b32.mak b/harbour/make_b32.mak index 999bac4096..0d6992d3ea 100644 --- a/harbour/make_b32.mak +++ b/harbour/make_b32.mak @@ -566,6 +566,20 @@ $(STANDARD_STATIC_CLIBS) $(MINIMAL_STATIC_HBLIBS) ! #********************************************************** +# HBMK build rule +#********************************************************** +$(HBMK_EXE) :: BasicLibs BasicExes StdLibs +$(HBMK_EXE) :: $(HBMK_EXE_OBJS) + @if exist "$(HBMK_EXE)" $(DEL) "$(HBMK_EXE)" > NUL + $(CC) @&&! +$(CFLAGS) +-e$(HBMK_EXE) +$(**: = ^ +) +$(STANDARD_STATIC_CLIBS) +$(MINIMAL_STATIC_HBLIBS) +! +#********************************************************** #********************************************************** # DLL Targets diff --git a/harbour/make_gcc.mak b/harbour/make_gcc.mak index 19f97d5b38..225df2051d 100644 --- a/harbour/make_gcc.mak +++ b/harbour/make_gcc.mak @@ -452,6 +452,10 @@ $(HBMAKE_EXE) :: StdLibs $(HBMAKE_EXE) :: $(HBMAKE_EXE_OBJS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) #********************************************************** +$(HBMK_EXE) :: StdLibs +$(HBMK_EXE) :: $(HBMK_EXE_OBJS) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) +#********************************************************** #********************************************************** # DLL Targets diff --git a/harbour/make_vc.mak b/harbour/make_vc.mak index 808276d820..9937a427ba 100644 --- a/harbour/make_vc.mak +++ b/harbour/make_vc.mak @@ -317,6 +317,9 @@ LDFLAGSDLL = /debug $(LDFLAGSDLL) {$(HBMAKE_DIR)}.c{$(OBJ_DIR)}$(OBJEXT):: $(CC) $(CLIBFLAGS) -Fo$(OBJ_DIR)\ $< #******************************************************* +{$(HBMK_DIR)}.c{$(OBJ_DIR)}$(OBJEXT):: + $(CC) $(CLIBFLAGS) -Fo$(OBJ_DIR)\ $< +#******************************************************* #******************************************************* # General *.prg --> *.obj COMPILE rules for STATIC Libraries @@ -457,6 +460,10 @@ LDFLAGSDLL = /debug $(LDFLAGSDLL) $(HB) $(HARBOURFLAGSEXE) -o$(OBJ_DIR)\ $< $(CC) $(CLIBFLAGS) -Fo$(OBJ_DIR)\ $(OBJ_DIR)\$(*B).c #******************************************************* +{$(HBMK_DIR)}.prg{$(OBJ_DIR)}$(OBJEXT): + $(HB) $(HARBOURFLAGSEXE) -o$(OBJ_DIR)\ $< + $(CC) $(CLIBFLAGS) -Fo$(OBJ_DIR)\ $(OBJ_DIR)\$(*B).c +#******************************************************* #******************************************************* # General *.c --> *.obj COMPILE rules for STATIC MT Libraries @@ -604,6 +611,9 @@ LDFLAGSDLL = /debug $(LDFLAGSDLL) {$(HBMAKE_DIR)}.c{$(DLL_OBJ_DIR)}$(OBJEXT):: $(CC) $(CEXEFLAGSDLL) -Fo$(DLL_OBJ_DIR)\ $< #******************************************************* +{$(HBMK_DIR)}.c{$(DLL_OBJ_DIR)}$(OBJEXT):: + $(CC) $(CEXEFLAGSDLL) -Fo$(DLL_OBJ_DIR)\ $< +#******************************************************* #******************************************************* # General *.prg --> *.obj COMPILE rules for SHARED Libraries @@ -748,6 +758,10 @@ LDFLAGSDLL = /debug $(LDFLAGSDLL) {$(HBMAKE_DIR)}.prg{$(DLL_OBJ_DIR)}$(OBJEXT): $(HB) $(HARBOURFLAGSEXE) -o$(DLL_OBJ_DIR)\ $< $(CC) $(CEXEFLAGSDLL) -Fo$(DLL_OBJ_DIR)\ $(DLL_OBJ_DIR)\$(*B).c +#******************************************************* +{$(HBMK_DIR)}.prg{$(DLL_OBJ_DIR)}$(OBJEXT): + $(HB) $(HARBOURFLAGSEXE) -o$(DLL_OBJ_DIR)\ $< + $(CC) $(CEXEFLAGSDLL) -Fo$(DLL_OBJ_DIR)\ $(DLL_OBJ_DIR)\$(*B).c #********************************************************** #********************************************************** @@ -968,6 +982,19 @@ $(MINIMAL_STATIC_HBLIBS) $(STANDARD_SYSLIBS) <<$(HB_KEEPSTATE) #********************************************************** +# HBMK build rule +#********************************************************** +$(HBMK_EXE) : $(HBMK_EXE_OBJS) + @if exist "$(HBMK_EXE)" $(DEL) "$(HBMK_EXE)" > nul + $(LINKER) @<< +$(LDFLAGS) +/out:$(HBMK_EXE) +$(**: = ^ +) +$(MINIMAL_STATIC_HBLIBS) +$(STANDARD_SYSLIBS) +<<$(HB_KEEPSTATE) +#********************************************************** #********************************************************** # DLL Targets diff --git a/harbour/utils/Makefile b/harbour/utils/Makefile index a06800ef14..84ca9fce29 100644 --- a/harbour/utils/Makefile +++ b/harbour/utils/Makefile @@ -10,6 +10,7 @@ DIRS=\ hbi18n \ hbdoc \ hbmake \ + hbmk \ $(HB_UTILS) \ # hbextern \ diff --git a/harbour/utils/hbmk/hbmk.prg b/harbour/utils/hbmk/hbmk.prg index 0a45d736fa..07e1f3c014 100644 --- a/harbour/utils/hbmk/hbmk.prg +++ b/harbour/utils/hbmk/hbmk.prg @@ -51,74 +51,93 @@ */ #include "common.ch" +#include "fileio.ch" + +/* TODO: Add support for more hbmk script features. */ FUNCTION Main() - /* Add missing libs */ LOCAL aLIB_BASE := {; - "hbcpage" ,; - "hbdebug" ,; + "hbcommon" ,; "hbrtl" ,; - "gtcgi" ,; - "gtstd" ,; - "gtpca" ,; - "hblang" ,; - "hbrdd" ,; "hbmacro" ,; "hbpp" ,; - "hbhsx" ,; - "hbsix" ,; - "hbcommon" ,; + "hbcpage" ,; + "hblang" ,; "hbpcre" ,; "hbzlib" ,; - "hbuddall" ,; + "hbextern" ,; + "gtcgi" ,; + "gtstd" ,; + "gtpca" } + + LOCAL aLIB_BASE_DEBUG := { "hbdebug" } + + LOCAL aLIB_BASE_ST := { "hbvm" } + LOCAL aLIB_BASE_MT := { "hbvmmt" } + + LOCAL aLIB_BASE_NULRDD := {; + "hbnulrdd" } + + LOCAL aLIB_BASE_RDD := {; + "hbrdd" ,; "hbusrrdd" ,; + "hbuddall" ,; + "hbhsx" ,; + "hbsix" ,; "rddntx" ,; "rddnsx" ,; "rddcdx" ,; "rddfpt" } - LOCAL aLIB_BASE_ST := { "hbvm" } - LOCAL aLIB_BASE_MT := { "hbvmmt" } + LOCAL s_cCOMP + LOCAL s_cARCH - LOCAL aLIB_BASE_bsd := { "gttrm", "gtxwc" } - LOCAL aLIB_BASE_darwin := { "gttrm", "gtxwc" } - LOCAL aLIB_BASE_dos := { "gtdos" } - LOCAL aLIB_BASE_hpux := { "gttrm", "gtxwc" } - LOCAL aLIB_BASE_linux := { "gttrm", "gtxwc" } - LOCAL aLIB_BASE_os2 := { "gtos2" } - LOCAL aLIB_BASE_sunos := { "gttrm", "gtxwc" } - LOCAL aLIB_BASE_win := { "gtwin", "gtwvt" } - - LOCAL s_COMP - LOCAL s_ARCH - - LOCAL s_HB_INSTALL_PREFIX - LOCAL s_HB_BIN_INSTALL - LOCAL s_HB_LIB_INSTALL - LOCAL s_HB_INC_INSTALL + LOCAL s_cHB_INSTALL_PREFIX + LOCAL s_cHB_BIN_INSTALL + LOCAL s_cHB_LIB_INSTALL + LOCAL s_cHB_INC_INSTALL LOCAL s_aPRG LOCAL s_aC + LOCAL s_aLIBSHARED LOCAL s_aLIB - LOCAL s_aOPT + LOCAL s_aLIBUSER + LOCAL s_aLIBHB + LOCAL s_aLIBHBGT + LOCAL s_aLIB3RD + LOCAL s_aLIBSYS + LOCAL s_aOPTP + LOCAL s_aOPTC + LOCAL s_aOPTL LOCAL s_cPROGNAME + LOCAL s_aOBJ + LOCAL s_aOBJUSER + LOCAL s_aCLEAN - LOCAL s_lGUI - LOCAL s_lMT - LOCAL s_lSHARED - LOCAL s_lDEBUG - - LOCAL s_BASEDIR + LOCAL s_lGUI := .F. + LOCAL s_lMT := .F. + LOCAL s_lSHARED := .F. + LOCAL s_lDEBUG := .F. + LOCAL s_lNULRDD := .F. LOCAL aCOMPDET LOCAL aCOMPSUP LOCAL cLibPrefix LOCAL cLibExt + LOCAL cObjExt LOCAL cCommand + LOCAL cOpt_CompC + LOCAL cOpt_Link + LOCAL cBin_CompPRG + LOCAL cBin_CompC + LOCAL cBin_Link + LOCAL nErrorLevel LOCAL tmp + LOCAL cScriptFile + LOCAL fhnd ShowHeader() @@ -127,173 +146,464 @@ FUNCTION Main() RETURN 9 ENDIF - s_BASEDIR := hb_DirBase() + /* Autodetect architecture */ - IF Empty( GetEnv( "HB_INSTALL_PREFIX" ) ) - DO CASE - CASE File( "harbour.*" ) ; s_HB_INSTALL_PREFIX := DirAddPathSep( hb_DirBase() ) + ".." - CASE File( "bin\harbour.*" ) ; s_HB_INSTALL_PREFIX := DirAddPathSep( hb_DirBase() ) - CASE File( "..\bin\harbour.*" ) ; s_HB_INSTALL_PREFIX := DirAddPathSep( hb_DirBase() ) + ".." - CASE File( "..\..\bin\harbour.*" ) ; s_HB_INSTALL_PREFIX := DirAddPathSep( hb_DirBase() ) + ".." + hb_osPathSeparator() + ".." - OTHERWISE - OutErr( "Error: HB_INSTALL_PREFIX not set, failed to autodetect." + hb_osNewLine() ) - RETURN 1 - ENDCASE - ELSE - s_HB_INSTALL_PREFIX := GetEnv( "HB_INSTALL_PREFIX" ) - ENDIF - IF Empty( GetEnv( "HB_BIN_INSTALL" ) ) - s_HB_BIN_INSTALL := DirAddPathSep( s_HB_INSTALL_PREFIX ) + "bin" - ENDIF - IF Empty( GetEnv( "HB_LIB_INSTALL" ) ) - s_HB_LIB_INSTALL := DirAddPathSep( s_HB_INSTALL_PREFIX ) + "lib" - ENDIF - IF Empty( GetEnv( "HB_INC_INSTALL" ) ) - s_HB_INC_INSTALL := DirAddPathSep( s_HB_INSTALL_PREFIX ) + "include" - ENDIF - - s_ARCH := GetEnv( "HB_ARCHITECTURE" ) + s_cARCH := GetEnv( "HB_ARCHITECTURE" ) IF Empty( GetEnv( "HB_ARCHITECTURE" ) ) #if defined( __PLATFORM__BSD ) - s_ARCH := "bsd" + s_cARCH := "bsd" #elif defined( __PLATFORM__DARWIN ) - s_ARCH := "darwin" + s_cARCH := "darwin" #elif defined( __PLATFORM__DOS ) - s_ARCH := "dos" + s_cARCH := "dos" #elif defined( __PLATFORM__HPUX ) - s_ARCH := "hpux" + s_cARCH := "hpux" #elif defined( __PLATFORM__LINUX ) - s_ARCH := "linux" + s_cARCH := "linux" #elif defined( __PLATFORM__OS2 ) - s_ARCH := "os2" + s_cARCH := "os2" #elif defined( __PLATFORM__SUNOS ) - s_ARCH := "sunos" + s_cARCH := "sunos" #elif defined( __PLATFORM__WINDOWS ) - s_ARCH := "win" + s_cARCH := "win" #endif - OutStd( "Autodetected HB_ARCHITECTURE: " + s_ARCH + hb_osNewLine() ) + IF ! Empty( s_cARCH ) + OutStd( "hbmk: Autodetected HB_ARCHITECTURE: " + s_cARCH + hb_osNewLine() ) + ENDIF ENDIF + /* Setup architecture dependent data */ + DO CASE - CASE s_arch == "bsd" + CASE s_cARCH == "bsd" aCOMPSUP := { "gcc" } s_lSHARED := .T. - CASE s_arch == "darwin" + cBin_CompPRG := "harbour" + s_aLIBHBGT := { "gttrm", "gtxwc" } + CASE s_cARCH == "darwin" aCOMPSUP := { "gcc" } - s_lSHARED := .F. - CASE s_arch == "dos" - aCOMPDET := { { "gcc.exe", "djgpp" } } - aCOMPSUP := { "bcc16", "djgpp", "owatcom", "rsx32" } - s_lSHARED := .F. - CASE s_arch == "hpux" + cBin_CompPRG := "harbour" + s_aLIBHBGT := { "gttrm", "gtxwc" } + CASE s_cARCH == "hpux" aCOMPSUP := { "gcc" } s_lSHARED := .T. - CASE s_arch == "linux" + cBin_CompPRG := "harbour" + s_aLIBHBGT := { "gttrm", "gtxwc" } + CASE s_cARCH == "linux" aCOMPSUP := { "gcc", "gpp", "owatcom" } s_lSHARED := .T. - CASE s_arch == "os2" - aCOMPSUP := { "gcc", "icc" } - s_lSHARED := .F. - CASE s_arch == "sunos" + cBin_CompPRG := "harbour" + s_aLIBHBGT := { "gttrm", "gtxwc" } + CASE s_cARCH == "sunos" aCOMPSUP := { "gcc" } s_lSHARED := .T. - CASE s_arch == "win" + cBin_CompPRG := "harbour" + s_aLIBHBGT := { "gttrm", "gtxwc" } + CASE s_cARCH == "dos" + aCOMPDET := { { "gcc.exe", "djgpp" },; + { "wpp386.exe", "owatcom" } } + aCOMPSUP := { "djgpp", "gcc", "owatcom", "rsx32" } + cBin_CompPRG := "harbour.exe" + s_aLIBHBGT := { "gtdos" } + CASE s_cARCH == "os2" + aCOMPDET := { { "gcc.exe", "gcc" },; + { "icc.exe", "icc" },; + { "wpp386.exe", "owatcom" } } + aCOMPSUP := { "gcc", "icc" } + cBin_CompPRG := "harbour.exe" + s_aLIBHBGT := { "gtos2" } + CASE s_cARCH == "win" aCOMPDET := { { "gcc.exe" , "mingw" },; { "cl.exe" , "msvc" },; { "bcc32.exe" , "bcc32" },; { "wpp386.exe", "owatcom" } } aCOMPSUP := { "bcc32", "dm", "gcc", "icc", "mingw", "mingwce", "msvc", "msvcce", "owatcom", "pocc", "pocc64", "poccce", "rsxnt", "xcc" } - s_lSHARED := .F. + cBin_CompPRG := "harbour.exe" + s_aLIBHBGT := { "gtwin", "gtwvt", "gtgui" } OTHERWISE - OutErr( "Error: Architecture not properly set." + hb_osNewLine() ) + OutErr( "hbmk: Error: Architecture not properly set." + hb_osNewLine() ) RETURN 1 ENDCASE - s_COMP := GetEnv( "HB_COMPILER" ) + /* Autodetect compiler */ + + s_cCOMP := GetEnv( "HB_COMPILER" ) IF Empty( GetEnv( "HB_COMPILER" ) ) - FOR tmp := 1 TO Len( aCOMPDET ) - IF FindInPath( aCOMPDET[ tmp ][ 1 ] ) - s_COMP := aCOMPDET[ tmp ][ 2 ] - EXIT - ENDIF - NEXT - OutStd( "Autodetected HB_COMPILER: " + s_COMP + hb_osNewLine() ) + IF Len( aCOMPSUP ) == 1 + s_cCOMP := aCOMPSUP[ 1 ] + ELSEIF ! Empty( aCOMPDET ) + FOR tmp := 1 TO Len( aCOMPDET ) + IF FindInPath( aCOMPDET[ tmp ][ 1 ] ) + s_cCOMP := aCOMPDET[ tmp ][ 2 ] + EXIT + ENDIF + NEXT + ENDIF + IF ! Empty( s_cCOMP ) + OutStd( "hbmk: Autodetected HB_COMPILER: " + s_cCOMP + hb_osNewLine() ) + ENDIF ENDIF - IF AScan( aCOMPSUP, {|tmp| tmp == s_COMP } ) == 0 - OutErr( "Error: Compiler not properly set." + hb_osNewLine() ) + IF AScan( aCOMPSUP, {|tmp| tmp == s_cCOMP } ) == 0 + OutErr( "hbmk: Error: Compiler not properly set." + hb_osNewLine() ) RETURN 2 ENDIF + /* Autodetect Harbour environment */ + + IF Empty( GetEnv( "HB_INSTALL_PREFIX" ) ) + DO CASE + /* TOFIX: On *NIXes use installed location if the installed binary is run, otherwise use the local dirs */ +/* CASE hb_ProgName() == "/....." */ + CASE hb_FileExists( DirAddPathSep( hb_DirBase() ) + cBin_CompPRG ) ; s_cHB_INSTALL_PREFIX := DirAddPathSep( hb_DirBase() ) + ".." + CASE hb_FileExists( DirAddPathSep( hb_DirBase() ) + "bin" + hb_osPathSeparator() + cBin_CompPRG ) ; s_cHB_INSTALL_PREFIX := DirAddPathSep( hb_DirBase() ) + CASE hb_FileExists( DirAddPathSep( hb_DirBase() ) + ".." + hb_osPathSeparator() + ".." + hb_osPathSeparator() + "bin" + hb_osPathSeparator() + cBin_CompPRG ) ; s_cHB_INSTALL_PREFIX := DirAddPathSep( hb_DirBase() ) + ".." + hb_osPathSeparator() + ".." + OTHERWISE + OutErr( "hbmk: Error: HB_INSTALL_PREFIX not set, failed to autodetect." + hb_osNewLine() ) + RETURN 3 + ENDCASE + ELSE + s_cHB_INSTALL_PREFIX := GetEnv( "HB_INSTALL_PREFIX" ) + ENDIF + IF Empty( GetEnv( "HB_BIN_INSTALL" ) ) + s_cHB_BIN_INSTALL := DirAddPathSep( s_cHB_INSTALL_PREFIX ) + "bin" + ENDIF + IF Empty( GetEnv( "HB_LIB_INSTALL" ) ) + s_cHB_LIB_INSTALL := DirAddPathSep( s_cHB_INSTALL_PREFIX ) + "lib" + ENDIF + IF Empty( GetEnv( "HB_INC_INSTALL" ) ) + s_cHB_INC_INSTALL := DirAddPathSep( s_cHB_INSTALL_PREFIX ) + "include" + ENDIF + + /* Process command line */ + IF Lower( GetEnv( "GUI" ) ) == "yes" ; s_lGUI := .T. ; ENDIF IF Lower( GetEnv( "MT" ) ) == "yes" ; s_lMT := .T. ; ENDIF IF Lower( GetEnv( "SHARED" ) ) == "yes" ; s_lSHARED := .T. ; ENDIF IF Lower( GetEnv( "DEBUG" ) ) == "yes" ; s_lDEBUG := .T. ; ENDIF + IF Lower( GetEnv( "NULRDD" ) ) == "yes" ; s_lNULRDD := .T. ; ENDIF s_aPRG := {} - s_aC := {} - s_aLIB := {} - s_aOPT := {} + s_aC := {} + s_aLIBUSER := {} + s_aOBJUSER := {} + s_aOPTP := {} s_cPROGNAME := NIL FOR tmp := 1 TO PCount() DO CASE - CASE Lower( hb_PValue( tmp ) ) == "-gui" ; s_lGUI := .T. - CASE Lower( hb_PValue( tmp ) ) == "-mt" ; s_lMT := .T. - CASE Lower( hb_PValue( tmp ) ) == "-shared" ; s_lSHARED := .T. - CASE Lower( hb_PValue( tmp ) ) == "-static" ; s_lSHARED := .F. - CASE Lower( hb_PValue( tmp ) ) == "-debug" ; s_lDEBUG := .T. - CASE Left( hb_PValue( tmp ), 1 ) == "-" ; AAdd( s_aOPT, hb_PValue( tmp ) ) - CASE Left( hb_PValue( tmp ), 2 ) == "-l" ; AAdd( s_aLIB, SubStr( hb_PValue( tmp ), 2 ) ) - CASE Lower( ExtGet( hb_PValue( tmp ) ) ) == ".prg" ; AAdd( s_aPRG, hb_PValue( tmp ) ) ; DEFAULT s_cPROGNAME TO hb_PValue( tmp ) - CASE Lower( ExtGet( hb_PValue( tmp ) ) ) $ ".c|.cpp" ; AAdd( s_aC , hb_PValue( tmp ) ) ; DEFAULT s_cPROGNAME TO hb_PValue( tmp ) - CASE Lower( ExtGet( hb_PValue( tmp ) ) ) $ ".lib|.a" ; AAdd( s_aLIB, hb_PValue( tmp ) ) - OTHERWISE ; AAdd( s_aPRG, hb_PValue( tmp ) ) ; DEFAULT s_cPROGNAME TO hb_PValue( tmp ) + CASE Lower( hb_PValue( tmp ) ) == "-gui" ; s_lGUI := .T. + CASE Lower( hb_PValue( tmp ) ) == "-mt" ; s_lMT := .T. + CASE Lower( hb_PValue( tmp ) ) == "-shared" ; s_lSHARED := .T. + CASE Lower( hb_PValue( tmp ) ) == "-static" ; s_lSHARED := .F. + CASE Lower( hb_PValue( tmp ) ) == "-debug" ; s_lDEBUG := .T. + CASE Lower( hb_PValue( tmp ) ) == "-nulrdd" ; s_lNULRDD := .T. + CASE Left( hb_PValue( tmp ), 2 ) == "-o" ; s_cPROGNAME := SubStr( hb_PValue( tmp ), 3 ) + CASE Left( hb_PValue( tmp ), 2 ) == "-l" ; AAdd( s_aLIBUSER, SubStr( hb_PValue( tmp ), 3 ) ) + CASE Left( hb_PValue( tmp ), 1 ) == "-" ; AAdd( s_aOPTP , hb_PValue( tmp ) ) + CASE Lower( ExtGet( hb_PValue( tmp ) ) ) == ".prg" ; AAdd( s_aPRG , hb_PValue( tmp ) ) ; DEFAULT s_cPROGNAME TO hb_PValue( tmp ) + CASE Lower( ExtGet( hb_PValue( tmp ) ) ) $ ".o|.obj" ; AAdd( s_aOBJUSER, hb_PValue( tmp ) ) + CASE Lower( ExtGet( hb_PValue( tmp ) ) ) $ ".c|.cpp" ; AAdd( s_aC , hb_PValue( tmp ) ) ; DEFAULT s_cPROGNAME TO hb_PValue( tmp ) + CASE Lower( ExtGet( hb_PValue( tmp ) ) ) $ ".lib|.a" ; AAdd( s_aLIBUSER, hb_PValue( tmp ) ) + OTHERWISE ; AAdd( s_aPRG , hb_PValue( tmp ) ) ; DEFAULT s_cPROGNAME TO hb_PValue( tmp ) ENDCASE NEXT IF ( Len( s_aPRG ) + Len( s_aC ) ) == 0 - OutErr( "Error: No source files were specified." + hb_osNewLine() ) - RETURN 3 + OutErr( "hbmk: Error: No source files were specified." + hb_osNewLine() ) + RETURN 4 ENDIF + /* Merge user libs from command line and envvar. Command line has priority. */ + s_aLIBUSER := ArrayAJoin( { s_aLIBUSER, ListToArray( GetEnv( "HB_USER_LIBS" ) ) } ) + + /* Strip lib/obj names from extension. */ + ListDelExt( s_aLIBUSER ) + ListDelExt( s_aOBJUSER ) + + /* TOFIX: s_aLIBSHARED to be fixed for some *IX platforms. */ + DO CASE + CASE s_cARCH $ "bsd|hpux|linux|sunos" + s_aLIBSHARED := { iif( s_lMT, "harbourmt.so", "harbour.so" ) } + CASE s_cARCH == "darwin" + s_aLIBSHARED := { iif( s_lMT, "harbourmt.dylib", "harbour.dylib" ) } + CASE s_cARCH == "os2|win" + s_aLIBSHARED := { iif( s_lMT, "harbourmt", "harbour" ) } + OTHERWISE + s_aLIBSHARED := NIL + ENDCASE + + /* Harbour compilation */ + s_cPROGNAME := DirNameGet( s_cPROGNAME ) - /* Harbour */ - IF Len( s_aPRG ) > 0 - cCommand := DirAddPathSep( s_HB_BIN_INSTALL ) +; - "harbour" +; + cCommand := DirAddPathSep( s_cHB_BIN_INSTALL ) +; + cBin_CompPRG +; " " + ArrayToList( s_aPRG ) +; " -n -q0" +; - " -i" + s_HB_INC_INSTALL +; + " -i" + s_cHB_INC_INSTALL +; iif( ! Empty( GetEnv( "HB_USER_PRGFLAGS" ) ), " " + GetEnv( "HB_USER_PRGFLAGS" ), "" ) +; - iif( ! Empty( s_aOPT ), " " + ArrayToList( s_aOPT ), "" ) + iif( ! Empty( s_aOPTP ), " " + ArrayToList( s_aOPTP ), "" ) IF ( tmp := hb_run( cCommand ) ) != 0 - OutErr( "Error: Running Harbour compiler. " + hb_ntos( tmp ) + " '" + cCommand + "'" + hb_osNewLine() ) - RETURN 4 + OutErr( "hbmk: Error: Running Harbour compiler. " + hb_ntos( tmp ) + ": '" + cCommand + "'" + hb_osNewLine() ) + RETURN 5 ENDIF ENDIF - /* C */ + /* Assemble library list */ + + /* C compilation/linking */ + + s_aLIB3RD := {} + s_aLIBSYS := {} + s_aOPTC := {} + s_aOPTL := {} + s_aCLEAN := {} + + /* Command macros: + + {C} list of C files, + {O} list of object files, + {L} list of lib files, + {OPTC} C compiler flags (user + automatic), + {OPTL} linker flags (user + automatic), + {B} binary name, + {I} include path, + {A} lib path + */ DO CASE - CASE s_arch == "bsd" - CASE s_arch == "darwin" - CASE s_arch == "dos" - CASE s_arch == "hpux" - CASE s_arch == "linux" - CASE s_arch == "os2" - CASE s_arch == "sunos" - CASE s_arch == "win" + /* GCC family */ + CASE ( s_cARCH == "bsd" .AND. s_cCOMP == "gcc" ) .OR. ; + ( s_cARCH == "darwin" .AND. s_cCOMP == "gcc" ) .OR. ; + ( s_cARCH == "hpux" .AND. s_cCOMP == "gcc" ) .OR. ; + ( s_cARCH == "linux" .AND. s_cCOMP == "gcc" ) .OR. ; + ( s_cARCH == "sunos" .AND. s_cCOMP == "gcc" ) + + cLibPrefix := "-l" + cLibExt := NIL + cObjExt := ".o" + cBin_CompC := "gcc" + cOpt_CompC := "{C} -O3 -o{B} {OPTC} -I{I} -L{A} {L}" + + CASE ( s_cARCH == "win" .AND. s_cCOMP == "gcc" ) .OR. ; + ( s_cARCH == "win" .AND. s_cCOMP == "mingw" ) .OR. ; + ( s_cARCH == "os2" .AND. s_cCOMP == "gcc" ) + + cLibPrefix := "-l" + cLibExt := NIL + cObjExt := ".o" + cBin_CompC := "gcc" + cOpt_CompC := "{C} -O3 -mno-cygwin -o{B}.exe {OPTC} -I{I} -L{A} {L}" + + CASE s_cARCH == "dos" .AND. s_cCOMP == "djgpp" + + cLibPrefix := "-l" + cLibExt := NIL + cObjExt := ".o" + cBin_CompC := "gcc" + cOpt_CompC := "{C} -O3 -o{B}.exe {OPTC} -I{I} -L{A} {L}{SCRIPT}" + s_aLIBSYS := ArrayJoin( s_aLIBSYS, { "m" } ) + + CASE s_cARCH == "dos" .AND. s_cCOMP == "rsx32" + + cLibPrefix := "-l" + cLibExt := NIL + cObjExt := ".o" + cBin_CompC := "gcc" + cOpt_CompC := "{C} -O3 -Zrsx32 -o{B}.exe {OPTC} -I{I} -L{A} {L}" + + /* Watcom family */ + CASE s_cARCH == "dos" .AND. s_cCOMP == "owatcom" + cLibPrefix := "LIB " + cLibExt := ".lib" + cObjExt := ".obj" + cBin_CompC := "wpp386" + cOpt_CompC := "-j -w3 -5s -5r -fp5 -oxehtz -zq -zt0 -bt=DOS {OPTC} {C}" + cBin_Link := "wlink" + cOpt_Link := "OP osn=DOS OP stack=65536 OP CASEEXACT OP stub=cwstub.exe {OPTL} NAME {B}.exe {L}" + + CASE s_cARCH == "win" .AND. s_cCOMP == "owatcom" + cLibPrefix := "LIB " + cLibExt := ".lib" + cObjExt := ".obj" + cBin_CompC := "wpp386" + cOpt_CompC := "-j -w3 -5s -5r -fp5 -oxehtz -zq -zt0 -mf -bt=NT {OPTC} {C}" + cBin_Link := "wlink" + cOpt_Link := "OP osn=NT OP stack=65536 OP CASEEXACT {OPTL} NAME {B}.exe {L}" + s_aLIBSYS := ArrayJoin( s_aLIBSYS, { "kernel32", "user32", "wsock32" } ) + + CASE s_cARCH == "os2" .AND. s_cCOMP == "owatcom" + cLibPrefix := "LIB " + cLibExt := ".lib" + cObjExt := ".obj" + cBin_CompC := "wpp386" + cOpt_CompC := "-j -w3 -5s -5r -fp5 -oxehtz -zq -zt0 -mf -bt=OS2 {OPTC} {C}" + cBin_Link := "wlink" + cOpt_Link := "OP stack=65536 OP CASEEXACT {OPTL} NAME {B}.exe {L}" + + CASE s_cARCH == "linux" .AND. s_cCOMP == "owatcom" + /* TODO */ + + /* Misc */ + CASE s_cARCH == "win" .AND. s_cCOMP == "bcc32" + IF s_lDEBUG + AAdd( s_aOPTC, "-y -v" ) + ELSE + AAdd( s_aCLEAN, ExtSet( s_cPROGNAME, ".tds" ) ) + ENDIF + IF s_lGUI + AAdd( s_aOPTC, "-tW" ) + ENDIF + cLibPrefix := NIL + cLibExt := ".lib" + cObjExt := ".obj" + cBin_CompC := "bcc32" + cOpt_CompC := "-q -tWM -O2 -OS -Ov -Oi -Oc -d {OPTC} -I{I} -L{A} {C} {L}" + /* TOFIX: The two build systems should generate the same .dll name, otherwise + we can only be compatible with one of them. non-GNU is the common choice here. */ + s_aLIBSHARED := { iif( s_lMT, "harbourmt-11-b32", "harbour-11-b32" ), "hbmainstd", "hbmainwin", "hbcommon" } + + CASE s_cARCH == "win" .AND. s_cCOMP == "msvc" + IF s_lDEBUG + AAdd( s_aOPTC, "-MTd -Zi" ) + ENDIF + IF s_lGUI + AAdd( s_aOPTL, "/subsystem:windows" ) + ELSE + AAdd( s_aOPTL, "/subsystem:console" ) + ENDIF + cLibPrefix := NIL + cLibExt := ".lib" + cObjExt := ".obj" + cBin_CompC := "cl" + cOpt_CompC := "-nologo -W3 {OPTC} -I{I} {C} /link /libpath:{A} {OPTL} {L}" + s_aLIBSYS := ArrayJoin( s_aLIBSYS, { "user32", "wsock32", "advapi32", "gdi32" } ) + /* TOFIX: The two build systems should generate the same .dll name, otherwise + we can only be compatible with one of them. non-GNU is the common choice here. */ + s_aLIBSHARED := { iif( s_lMT, "harbourmt-11-vc", "harbour-11-vc" ), "hbmainstd", "hbmainwin", "hbcommon" } + + /* TODO */ + CASE s_cARCH == "win" .AND. s_cCOMP == "dm" + CASE s_cARCH == "win" .AND. s_cCOMP == "icc" + CASE s_cARCH == "win" .AND. s_cCOMP == "mingwce" + CASE s_cARCH == "win" .AND. s_cCOMP == "msvcce" + CASE s_cARCH == "win" .AND. s_cCOMP == "pocc" + CASE s_cARCH == "win" .AND. s_cCOMP == "pocc64" + CASE s_cARCH == "win" .AND. s_cCOMP == "poccce" + CASE s_cARCH == "win" .AND. s_cCOMP == "rsxnt" + CASE s_cARCH == "win" .AND. s_cCOMP == "xcc" + CASE s_cARCH == "os2" .AND. s_cCOMP == "icc" ENDCASE + IF s_lSHARED .AND. ! Empty( s_aLIBSHARED ) + s_aLIBHB := s_aLIBSHARED + ELSE + s_aLIBHB := ArrayAJoin( { aLIB_BASE,; + aLIB_BASE_DEBUG,; + iif( s_lMT, aLIB_BASE_MT, aLIB_BASE_ST ),; + iif( s_lNULRDD, aLIB_BASE_NULRDD, aLIB_BASE_RDD ),; + s_aLIBHBGT } ) + ENDIF + + /* Merge lib lists. */ + s_aLIB := ArrayAJoin( { s_aLIBHB, s_aLIBUSER, s_aLIB3RD, s_aLIBSYS } ) + /* Dress lib names. */ + s_aLIB := ListCook( s_aLIB, cLibPrefix, cLibExt ) + /* Dress obj names. */ + s_aOBJ := ListCook( ArrayJoin( s_aPRG, s_aC ), NIL, cObjExt ) + s_aOBJUSER := ListCook( s_aOBJUSER, NIL, cObjExt ) + + nErrorLevel := 0 + + IF ! Empty( cOpt_CompC ) + + /* Compiling */ + + cOpt_CompC := StrTran( cOpt_CompC, "{C}" , ArrayToList( ArrayJoin( ListCook( s_aPRG, "", ".c" ), s_aC ) ) ) + cOpt_CompC := StrTran( cOpt_CompC, "{O}" , ArrayToList( s_aOBJ ) ) + cOpt_CompC := StrTran( cOpt_CompC, "{OUSR}", ArrayToList( s_aOBJUSER ) ) + cOpt_CompC := StrTran( cOpt_CompC, "{L}" , ArrayToList( s_aLIB ) ) + cOpt_CompC := StrTran( cOpt_CompC, "{OPTC}", GetEnv( "HB_USER_CFLAGS" ) + " " + ArrayToList( s_aOPTC ) ) + cOpt_CompC := StrTran( cOpt_CompC, "{B}" , s_cPROGNAME ) + cOpt_CompC := StrTran( cOpt_CompC, "{I}" , s_cHB_INC_INSTALL ) + cOpt_CompC := StrTran( cOpt_CompC, "{A}" , s_cHB_LIB_INSTALL ) + + cOpt_CompC := AllTrim( cOpt_CompC ) + + /* Handle moving the whole command line to a script, if requested. */ + IF "{SCRIPT}" $ cOpt_CompC + fhnd := hb_FTempCreateEx( @cScriptFile ) + IF fhnd != F_ERROR + FWrite( fhnd, StrTran( cOpt_CompC, "{SCRIPT}", "" ) ) + FClose( fhnd ) + cOpt_CompC := "@" + cScriptFile + ELSE + OutErr( "hbmk: Error: C compiler script couldn't be created, continuing in command line." + hb_osNewLine() ) + ENDIF + ENDIF + + cCommand := cBin_CompC + " " + cOpt_CompC + + IF ( tmp := hb_run( cCommand ) ) != 0 + OutErr( "hbmk: Error: Running C compiler. " + hb_ntos( tmp ) + ": '" + cCommand + "'" + hb_osNewLine() ) + nErrorLevel := 6 + ENDIF + + IF ! Empty( cScriptFile ) + FErase( cScriptFile ) + ENDIF + + IF ! Empty( cOpt_Link ) .AND. nErrorLevel == 0 + + /* Linking */ + + cOpt_Link := StrTran( cOpt_Link, "{O}" , ArrayToList( ArrayJoin( s_aOBJ, s_aOBJUSER ) ) ) + cOpt_Link := StrTran( cOpt_Link, "{L}" , ArrayToList( s_aLIB ) ) + cOpt_Link := StrTran( cOpt_Link, "{OPTL}", GetEnv( "HB_USER_LDFLAGS" ) + " " + ArrayToList( s_aOPTL ) ) + cOpt_Link := StrTran( cOpt_Link, "{B}" , s_cPROGNAME ) + cOpt_Link := StrTran( cOpt_Link, "{A}" , s_cHB_LIB_INSTALL ) + + cOpt_Link := AllTrim( cOpt_Link ) + + /* Handle moving the whole command line to a script, if requested. */ + IF "{SCRIPT}" $ cOpt_Link + fhnd := hb_FTempCreateEx( @cScriptFile ) + IF fhnd != F_ERROR + FWrite( fhnd, StrTran( cOpt_CompC, "{SCRIPT}", "" ) ) + FClose( fhnd ) + cOpt_Link := "@" + cScriptFile + ELSE + OutErr( "hbmk: Error: Link script couldn't be created, continuing in command line." + hb_osNewLine() ) + ENDIF + ENDIF + + cCommand := cBin_Link + " " + cOpt_Link + + IF ( tmp := hb_run( cCommand ) ) != 0 + OutErr( "hbmk: Error: Running linker. " + hb_ntos( tmp ) + ": '" + cCommand + "'" + hb_osNewLine() ) + nErrorLevel := 7 + ENDIF + + IF ! Empty( cScriptFile ) + FErase( cScriptFile ) + ENDIF + ENDIF + ELSE + OutErr( "hbmk: Error: This compiler/platform isn't implemented." + hb_osNewLine() ) + nErrorLevel := 8 + ENDIF + /* Cleanup */ - RETURN 0 + AEval( s_aOBJ, {|tmp| FErase( tmp ) } ) + AEval( s_aCLEAN, {|tmp| FErase( tmp ) } ) + + RETURN nErrorLevel STATIC FUNCTION FindInPath( cFileName ) LOCAL cPATH @@ -306,33 +616,104 @@ STATIC FUNCTION FindInPath( cFileName ) ENDIF cPATH := GetEnv( "PATH" ) - nCount := hb_TokenCount( cPATH, hb_osPathListSeparator() ) + IF ! Empty( cPATH ) + nCount := hb_TokenCount( cPATH, hb_osPathListSeparator() ) - FOR tmp := 1 TO nCount - cDir := hb_TokenGet( cPATH, tmp, hb_osPathListSeparator() ) - IF Left( cDir, 1 ) == Chr( 34 ) .AND. Right( cDir, 1 ) == Chr( 34 ) - cDir := SubStr( cDir, 2, Len( cDir ) - 2 ) - ENDIF - IF hb_FileExists( DirAddPathSep( cDir ) + cFileName ) - RETURN .T. - ENDIF - NEXT + FOR tmp := 1 TO nCount + cDir := hb_TokenGet( cPATH, tmp, hb_osPathListSeparator() ) + IF Left( cDir, 1 ) == Chr( 34 ) .AND. Right( cDir, 1 ) == Chr( 34 ) + cDir := SubStr( cDir, 2, Len( cDir ) - 2 ) + ENDIF + IF hb_FileExists( DirAddPathSep( cDir ) + cFileName ) + RETURN .T. + ENDIF + NEXT + ENDIF RETURN .F. -STATIC FUNCTION ArrayToList( aArray ) +STATIC FUNCTION ArrayJoin( array1, array2 ) + LOCAL array := AClone( array1 ) + LOCAL nLen1 := Len( array ) + + ASize( array, nLen1 + Len( array2 ) ) + + RETURN ACopy( array2, array, , , nLen1 + 1 ) + +STATIC FUNCTION ArrayAJoin( array ) + LOCAL tmp + LOCAL nLenArray := Len( array ) + LOCAL nLen + LOCAL nPos := Len( array[ 1 ] ) + 1 + + nLen := 0 + FOR tmp := 1 TO nLenArray + nLen += Len( array[ tmp ] ) + NEXT + + ASize( array[ 1 ], nLen ) + + FOR tmp := 2 TO nLenArray + ACopy( array[ tmp ], array[ 1 ], , , nPos ) + nPos += Len( array[ tmp ] ) + NEXT + + RETURN array[ 1 ] + +STATIC FUNCTION ListDelExt( array ) + LOCAL tmp + + FOR tmp := 1 TO Len( array ) + array[ tmp ] := DirNameGet( array[ tmp ] ) + NEXT + + RETURN array + +/* Append optional prefix and optional extension to all members */ +STATIC FUNCTION ListCook( array, cPrefix, cExt ) + LOCAL tmp + + DEFAULT cPrefix TO "" + + FOR tmp := 1 TO Len( array ) + array[ tmp ] := cPrefix + array[ tmp ] + IF ISCHARACTER( cExt ) + array[ tmp ] := ExtSet( array[ tmp ], cExt ) + ENDIF + NEXT + + RETURN array + +STATIC FUNCTION ArrayToList( array ) LOCAL cString := "" LOCAL tmp - FOR tmp := 1 TO Len( aArray ) - cString += aArray[ tmp ] - IF tmp < Len( aArray ) + FOR tmp := 1 TO Len( array ) + cString += array[ tmp ] + IF tmp < Len( array ) cString += " " ENDIF NEXT RETURN cString +STATIC FUNCTION ListToArray( cList ) + LOCAL array := {} + LOCAL nCount + LOCAL tmp + + IF ! Empty( cList ) + nCount := hb_TokenCount( cList, " " ) + + array := ASize( array, nCount ) + + FOR tmp := 1 TO nCount + array[ tmp ] := hb_TokenGet( cList, tmp, " " ) + NEXT + ENDIF + + RETURN array + STATIC FUNCTION DirAddPathSep( cDir ) IF ! Empty( cDir ) .AND. !( Right( cDir, 1 ) == hb_osPathSeparator() ) @@ -374,36 +755,34 @@ STATIC PROCEDURE ShowHeader() STATIC PROCEDURE ShowHelp() LOCAL aText := {; - "Usage: hbmk [-mt] [-gui] [-shared] [-debug] " ,; + "Usage: hbmk [options] [-l] [-o]" ,; + "" ,; + "Options:" ,; + " -o output file name" ,; + " -static|-shared link with static/shared libs" ,; + " -mt link with multi-thread libs" ,; + " -l link with library" ,; + " -L additional path to search for libraries" ,; + " -nulrdd link with nulrdd" ,; + " -gui create GUI executable" ,; + " -debug add debug info" ,; "" ,; "Notes:" ,; "" ,; - " - 'filename' is the .prg filename (without extension on pre-NT systems)." ,; " - Don't forget to create a MAIN() function in your application." ,; - " - Environment variables HB_ARCHITECTURE, HB_COMPILER must be set." ,; - " The following values are currently supported:" ,; + " - Multiple -l, -o parameters are accepted." ,; + " - Defaults and feature support varies by architecture/compiler." ,; "" ,; - " HB_ARCHITECTURE:" ,; - " - dos" ,; - " - win" ,; - " - os2" ,; + " HB_COMPILER values supported for each HB_ARCHITECURE:" ,; "" ,; - " HB_COMPILER:" ,; - " - When HB_ARCHITECTURE=win" ,; - " - msvc (Microsoft Visual C++, Windows 32/64-bit)" ,; - " - mingw (MinGW GNU C, Windows 32-bit)" ,; - " - gcc (Cygnus/Cygwin GNU C, Windows 32-bit)" ,; - " - bcc32 (Borland C++ 4.x, 5.x, 6.x, Windows 32-bit)" ,; - " - owatcom (OpenWatcom, Windows 32-bit)" ,; - " - rxsnt (EMX/RSXNT/Windows GNU C, Windows 32-bit)" ,; - " - When HB_ARCHITECTURE=os2" ,; - " - gcc (EMX GNU C, OS/2 32-bit)" ,; - " - icc (IBM Visual Age C++ 3.0, OS/2 32-bit)" ,; - " - owatcom (OpenWatcom, OS/2 32-bit)" ,; - " - When HB_ARCHITECTURE=dos" ,; - " - djgpp (Delorie GNU C, DOS 32-bit)" ,; - " - owatcom (OpenWatcom, DOS 32-bit)" ,; - " - rxs32 (EMX/RSXNT/DOS GNU C, DOS 32-bit)" } + " bsd : gcc",; + " darwin : gcc" ,; + " hpux : gcc" ,; + " sunos : gcc" ,; + " linux : gcc, owatcom" ,; + " win : gcc, mingw, msvc, bcc32, owatcom, rsxnt, pocc, dmc" ,; + " os2 : gcc, owatcom, icc" ,; + " dos : gcc, djgpp, owatcom, rsx32" } AEval( aText, {|tmp| OutStd( tmp + hb_osNewLine() ) } )