O que eu uso aqui:
rem d:\tools\util\c.bat
D:\fontes\build\build.exe %*
...
E no build.exe, coloquei tudo que é checagem que eu achei que valeria a pena
/*
BUILD - PRE-COMPILACAO
José Quintas
2021.10.22 - ShellExecuteOpen() não STATIC pra atender errorsys
*/
// HB_USER_CFLAGS
// -Wno-null-dereference -Wno-cast-function-type -Wno-return-local-addr
ANNOUNCE HB_GTSYS
REQUEST errorsys
#include "directry.ch"
STATIC stErro := .F.
FUNCTION Main( ... )
LOCAL aParams, aSignList := {}
SetMode( 28, 90 )
SetColor( "W/B" )
aParams := hb_AParams()
CheckGetEnv()
CheckPath( @aSignList )
checkHbmkHbc()
CheckBuild()
WriteBat( aParams, aSignList )
AEval( Directory( "c:\temp\ze_resXML.*" ), { | e | fErase( "c:\temp\" + e[ F_NAME ] ) } )
IF stErro
Inkey(0)
ENDIF
RETURN Nil
STATIC FUNCTION WriteBat( aParams, aSignList )
LOCAL oElement, cPath, cCmd := "", cBatFile := "d:\tools\util\c.bat", cFile
cPath := Upper( hb_cwd() )
IF ! Empty( aSignList )
FOR EACH cFile IN aSignList
cCmd += "call assina " + cFile + hb_Eol()
NEXT
ENDIF
IF Len( aParams ) != 0 .AND. aParams[ 1 ] == "/cmd"
hb_ADel( aParams, 1, .T. )
ELSE
IF AScan( aParams, { | e | e $ "|-w0|-w1|-w2|-w3|" } ) == 0
AAdd( aParams, "-w3" )
ENDIF
IF AScan( aParams, { | e | e $ "|-es0|-es1|-es2|" } ) == 0
AAdd( aParams, "-es2" )
ENDIF
IF AScan( aParams, "-m" ) == 0
AAdd( aParams, "-m" )
ENDIF
IF ASCan( aParams, "-n" ) == 0
AAdd( aParams, "-n" )
ENDIF
IF Len( Directory( "*.hbp" ) ) != 0
AAdd( aParams, "*.hbp" )
ELSEIF Len( Directory( "*.prg" ) ) != 0
AAdd( aParams, "*.prg" )
AAdd( aParams, "*.rc" )
ELSE
ShowNormal( hb_cwd() )
ENDIF
ENDIF
AAdd( aParams, "-strip" )
AAdd( aParams, "-compr" )
AAdd( aParams, "-workdir=c:\temp" )
AAdd( aParams, "-q" )
AAdd( aParams, "-I" + hb_FNameDir( hb_ProgName() ) )
cCmd += "HBMK2 "
FOR EACH oElement IN aParams
cCmd += oElement + " "
NEXT
cCmd := hb_ProgName() + " %*" + hb_Eol() + cCmd + hb_Eol()
DO CASE
CASE "\SJPA\" $ cPath; cCmd += "if exist ..\sjpa.exe call assina.bat ..\sjpa.exe" + hb_Eol()
CASE "\HAROLDO\" $ cPath; cCmd += "if exist hl.exe call assina.bat hl.exe" + hb_Eol()
CASE "\BUILD\" $ cPath; cCmd += "if exist build.exe call assina.bat build.exe" + hb_Eol()
CASE "\INTEGRA\" $ cPath; cCmd += "if exist jpa.exe call assina.bat jpa.exe" + hb_Eol()
ENDCASE
IF ! hb_DirExists( "c:\temp" )
hb_DirCreate( "c:\temp" )
ShowAlert( "Created c:\temp" )
ENDIF
//ShowNormal( "Atualizando " + cBatFile )
hb_MemoWrit( cBatFile, cCmd )
RETURN Nil
STATIC FUNCTION CheckHbmkHbc()
LOCAL lUpdate := .F., cParam, cTxt := "", cFileHbmk, cPath
LOCAL aParams := { ;
"mt=yes", ;
"gui=yes", ;
"strip=yes", ;
"fullstatic=yes", ;
"{hbexe}compr=yes", ;
"libpaths=d:/github/sefazclass", ;
"libpaths=d:/fontes/integra/libjpa", ;
"libpaths=d:/github/hwgui", ;
"PRGFLAGS=-m -n -w3 -es2 -ge1 -DMT_EXPERIMENTAL -DLEGACY_LEVEL5" }
//"{mingw}CFLAGS=" + ;
//" -Wno-implicit-fallthrough" + ;
//" -Wno-cast-function-type" + ;
//" -Wno-misleading-indentation", ;
cPath := CheckFileOnPath( "hbmk2.exe" )
IF Empty( cPath )
ShowAlert( "hbmk2.exe not found on PATH to check hbmk.hbc" )
RETURN Nil
ENDIF
IF Right( cPath, 1 ) != "\"
cPath += "\"
ENDIF
cFileHbmk := cPath + "hbmk.hbc"
IF File( cFileHbmk )
cTxt := MemoRead( cFileHbmk )
IF Right( cTxt, 2 ) != hb_Eol()
cTxt += hb_Eol()
ENDIF
ENDIF
IF "xharbour" $ Lower( cPath )
AAdd( aParams, "-xhb" )
ENDIF
FOR EACH cParam IN aParams
IF ! cParam $ cTxt
cTxt += cParam + hb_Eol()
ShowAlert( "hbmk.hbc adding " + cParam )
stErro := .T.
lUpdate := .T.
ENDIF
NEXT
IF lUpdate
hb_MemoWrit( cFileHbmk, cTxt )
ENDIF
RETURN Nil
STATIC FUNCTION CheckGetEnv()
LOCAL oElement
LOCAL aList := { ;
{ "HB_BUILD_DYN", "no" }, ;
{ "HB_BUILD_CONTRIB_DYN", "no" }, ;
{ "HB_BUILD_STRIP", "all" }, ;
{ "HB_BUILD_SHARED", "no" }, ;
{ "HB_COMPILER", "mingw" }, ;
{ "HB_INSTALL_PREFIX", "d:\harbour" }, ;
{ "HG_ROOT", "d:\github\oohg" } }
//{ "HB_BUILD_MODE", "cpp" } }
// { "HB_USER_CFLAGS", "-Wno-null-dereference -Wno-cast-function-type -Wno-return-local-addr" } }
/*
{ "HB_WITH_ADS", "no" }, ;
{ "HB_WITH_CURL", "no" }, ;
{ "HB_WITH_CAIRO", "no" }, ;
{ "HB_WITH_RABBITMQ", "no" }, ;
{ "HB_WITH_FIREBIRD", "no" }, ;
{ "HB_WITH_FREEIMAGE", "no" }, ;
{ "HB_WITH_ICU", "no" }, ;
{ "HB_WITH_GD", "no" }, ;
{ "HB_WITH_GS", "no" }, ;
{ "HB_WITH_LIBMAGIC", "no" }, ;
{ "HB_WITH_MYSQL", "no" }, ;
{ "HB_WITH_OPENSSL", "no" }, ;
{ "HB_WITH_PGSQL", "no" }, ;
{ "HB_WITH_OCILIB", "no" } }
*/
FOR EACH oElement IN aList
IF GetEnv( oElement[ 1 ] ) != oElement[ 2 ] .OR. Empty( GetEnv( oElement[ 1 ] ) )
ShowAlert( "Not found SET " + oElement[ 1 ] + "=" + oElement[ 2 ] )
ShellExecuteOpen( "setx", oElement[ 1 ] + " " + oElement[ 2 ],, 0 )
ENDIF
NEXT
RETURN Nil
STATIC FUNCTION CheckPath( aSignList )
LOCAL cFile, cPathFile, cPath, aPathList, cItem, lChanged := .F., cDefault
aPathList := hb_RegExSplit( ";", GetEnv( "PATH" ) )
FOR EACH cPath IN { "d:\harbour\bin", "d:\harbour\comp\mingw32\bin", "d:\harbour\comp\mingw64\bin", "d:\tools\util" } // "c:\msys64\mingw32\bin",
IF ASCan( aPathList, { | e | Lower( cPath ) $ Lower( e ) } ) == 0
ShowAlert( "Adding PATH " + cPath )
AAdd( aPathList, cPath )
lChanged := .T.
ENDIF
NEXT
IF lChanged
ShellExecuteOpen( "setx", "PATH ." )
cDefault := GetEnv( "PATH" )
cPath := ""
FOR EACH cItem IN aPathList
IF ! Lower( cItem ) + ";" $ Lower( cDefault + ";" + cPath + ";" )
IF ! Empty( cPath )
cPath += ";"
ENDIF
IF " " $ cItem
cPath += ["] + cItem + ["]
ELSE
cPath += cItem
ENDIF
ENDIF
NEXT
ShellExecuteOpen( "setx", "PATH " + cPath )
ENDIF
FOR EACH cFile IN { "c.bat" }
IF Empty( CheckFileOnPath( cFile ) )
ShowAlert( cFile + " not in PATH" )
ShowAlert( "Remember run build.exe from explorer, and re-open cmd window" )
ENDIF
NEXT
FOR EACH cFile IN { "hbmk2.exe", "harbour.exe" } // "upx.exe", "mingw32-make.exe", "gcc.exe" }
cPathFile := CheckFileOnPath( cFile )
IF Empty( cPathFile )
ShowAlert( cFile + " not in PATH" )
ELSEIF ! TestExeAssinado( cPathFile + cFile )
AAdd( aSignList, cPathFile + cFile )
ShowAlert( cPathFile + cFile + " nao assinado" )
ENDIF
NEXT
RETURN Nil
STATIC FUNCTION CheckFileOnPath( cFile )
LOCAL cPath, cPathFile
cFile := Lower( cFile )
FOR EACH cPath IN hb_RegExSplit( ";", GetEnv( "PATH" ) )
IF Right( cPath, 1 ) != "\"
cPath := cPath + "\"
ENDIF
IF File( cPath + cFile )
cPathFile := cPath
EXIT
ENDIF
NEXT
RETURN cPathFile
STATIC FUNCTION CheckBuild()
LOCAL cDateTime, cTxt, cFileName, hSetup, cLastPath
cFileName := hb_FNameDir( hb_ProgName() ) + hb_FNameName( hb_ProgName() )
hSetup := hb_JsonDecode( MemoRead( cFileName + ".json" ) )
IF ValType( hSetup ) != "H"
hSetup := hb_Hash()
ENDIF
IF ! hb_HHasKey( hSetup, "LastPath" )
hb_HSet( hSetup, "LastPath", "" )
ENDIF
IF ! hb_HHasKey( hSetup, "TotalCount" )
hb_HSet( hSetup, "TotalCount", 0 )
ENDIF
IF ! hb_HHasKey( hSetup, "YearCount" )
hb_HSet( hSetup, "YearCount", 0 )
ENDIF
IF ! hb_HHasKey( hSetup, "MonthCount" )
hb_HSet( hSetup, "MonthCount", 0 )
ENDIF
IF ! hb_HHasKey( hSetup, "DayCount" )
hb_HSet( hSetup, "DayCount", 0 )
ENDIF
IF ! hb_HHasKey( hSetup, "LastBuildDate" )
hb_HSet( hSetup, "LastBuildDate", Dtos( Date() ) )
ENDIF
cDateTime := Dtos( Date() ) + Substr( Time(), 1, 2 ) + Substr( Time(), 4, 2 )
cLastPath := hSetup[ "LastPath" ]
IF Day( Date() ) != Day( Stod( hSetup[ "LastBuildDate" ] ) )
hSetup[ "DayCount" ] := 0
ENDIF
IF Month( Date() ) != Month( Stod( hSetup[ "LastBuildDate" ] ) )
hSetup[ "MonthCount" ] := 0
ENDIF
IF Year( Date() ) != Year( Stod( hSetup[ "LastBuildDate" ] ) )
hSetup[ "YearCount" ] := 0
ENDIF
hSetup[ "TotalCount" ] += 1
hSetup[ "YearCount" ] += 1
hSetup[ "MonthCount" ] += 1
hSetup[ "DayCount" ] += 1
hSetup[ "LastPath" ] := hb_cwd()
hSetup[ "LastBuildDate" ] := Dtos( Date() )
hb_MemoWrit( cFileName + ".json", hb_JsonEncode( hSetup ) )
IF ! Upper( cLastPath ) == Upper( hb_cwd() )
DeleteContent( "c:\temp", .F. )
// DeleteContent( "c:\users\joseq\appdata\local\temp", .F. )
ENDIF
cTxt := "#define JOSEQUINTAS_VERSAO " + ["] + Transform( cDateTime, "@R 9999.99.99.9999" ) + ["] + hb_Eol()
cTxt += "#define JOSEQUINTAS_VERSAO_RC " + Transform( cDateTime, "@R 9999,99,99,9999" ) + hb_Eol()
hb_MemoWrit( cFileName + ".ch", cTxt )
IF File( "build.ch" ) // BHP ou projeto extra
hb_MemoWrit( "build.ch", cTxt )
ENDIF
AEval( Directory( "*.upx" ), { | e | fErase( e[ F_NAME ] ) } )
//ShowNormal( "Build atual " + cDateTime )
RETURN Nil
STATIC FUNCTION DeleteContent( cFolder, lDeleteFolder )
LOCAL oFiles, oFile, lDelete
hb_Default( @lDeleteFolder, .F. )
ShowNormal( "Delete on " + cFolder )
oFiles := Directory( cFolder + "\*.*", "D" )
FOR EACH oFile IN oFiles
IF "D" $ oFile[ F_ATTR ]
IF oFile[ F_NAME ] != "." .AND. oFile[ F_NAME ] != ".."
DeleteContent( cFolder + "\" + oFile[ F_NAME ], .T. )
ENDIF
ELSE
lDelete := .T.
DO CASE
CASE hb_FNameExt( oFile[ F_NAME ] ) == ".c"
CASE hb_FNameExt( oFile[ F_NAME ] ) == ".o"
CASE ASCan( { ".PRG", ".DBF", ".CH", ".HBP", ".RC" }, { | e | e == Upper( hb_FNameExt( oFile[ F_NAME ] ) ) } ) != 0
lDelete := .F.
CASE oFile[ F_DATE ] != Date()
CASE Left( oFile[ F_TIME ], 4 ) != Left( Time(), 4 )
OTHERWISE
lDelete := .F.
ENDCASE
IF lDelete
ShowNormal( "Deleting " + cFolder + "\" + oFile[ F_NAME ] )
fErase( cFolder + "\" + oFile[ F_NAME ] )
ENDIF
ENDIF
NEXT
IF lDeleteFolder .AND. Len( Directory( cFolder + "\*.*" ) ) == 0
DirRemove( cFolder )
ENDIF
RETURN Nil
FUNCTION HB_GT_SYS()
REQUEST HB_GT_WVG_DEFAULT
RETURN Nil
FUNCTION AppVersaoExe()
RETURN ""
FUNCTION AppUserName()
RETURN ""
STATIC FUNCTION TestExeAssinado( cFileName )
LOCAL oSignedCode, lOk := .F.
BEGIN SEQUENCE WITH __BreakBlock()
oSignedCode := win_OleCreateObject( "CAPICOM.SignedCode" )
oSignedCode:FileName := cFileName
oSignedCode:Verify()
lOk := .T.
ENDSEQUENCE
IF ! lOk
ShowAlert( "Not installed CAPICOM and/or EXE not signed" )
ENDIF
RETURN lOk
STATIC FUNCTION ShowNormal( cText )
? cText
RETURN Nil
STATIC FUNCTION ShowAlert( cText )
LOCAL cSetColor := SetColor( "N/GR*" )
? cText
SetColor( cSetColor )
stErro := .T.
Inkey(2)
RETURN Nil
FUNCTION ShellExecuteOpen( cFileName, cParameters, cPath, nShow )
wapi_ShellExecute( Nil, "open", cFileName, cParameters, cPath, hb_DefaultValue( nShow, 1 ) )
RETURN Nil
PROCEDURE HB_GTSYS
REQUEST HB_GT_WVG_DEFAULT
RETURN
/*
STATIC FUNCTION ShellExecuteRunAs( cFileName, cParameters, nShow )
wapi_ShellExecute( Nil, "RunAs", cFileName, cParameters,, hb_DefaultValue( nShow, WIN_SW_SHOWNORMAL ) )
RETURN Nil
*/
/*
dialog em resource com mingw
#include <afxres.h>
*/
Note que pelo programa:
- assino os EXEs que precisam ser assinados
- confiro e CRIO variáveis de ambiente
- confiro se os programas necessários estão no PATH
- confiro se HBMK2.EXE e HARBOUR.EXE estão assinados
- confiro se o harbour\bin\hbmk.hbc está criado e contém minha configuração default
- verifico se mudei de projeto/path de projeto, e apago \temp\*.*
- acrescento meus defaults de compilação
- procuro se a pasta tem HBP, se tiver mais de um já gera pra todos
- se não existir HBP, uso toda a pasta como compilação
- APAGO ARQUIVOS DE RESOURCE HARBOUR, porque o HBMK2 não consegue validar se teve alteração nisso
(aquilo de #pragma binarystreaminclude "arquivo.jpg" por exemplo)
Se eu pegar uma máquina zerada, é só rodar meu build.exe como administrador e ela fica pronta.
e pra compilar, digito C<ENTER>
pode aproveitar pra isso de usar o compilador de resource do borland c.
nota: no Borland C, se compilar .RES com nome repetido tudo bem, mas no mingw acusa erro e não deixa. De qualquer forma, é esquisito ter Ãcones com mesmo nome.... se não me engano na minigui isso acontece, ter Ãcone de impressora em mais de um RES.