2020-04-07 10:37:33 +02:00
from invoke import task , context , Exit
2019-01-08 12:48:27 +01:00
import os
import subprocess
from colorama import *
import glob
2019-10-15 12:51:08 +02:00
from shutil import copy2 , rmtree , copytree
2019-01-08 12:48:27 +01:00
from datetime import datetime
2019-01-29 17:59:02 +01:00
import pathlib
2020-02-03 10:51:40 +01:00
from typing import *
2019-01-08 12:48:27 +01:00
from pathlib import Path
init ( )
g_releases_path = " releases "
g_output = " bin "
g_output_folder = " " # defined at runtime
2020-04-07 10:37:33 +02:00
g_version = " DEV "
2019-01-08 12:48:27 +01:00
2023-11-06 14:46:39 +01:00
delphi_versions = [
2023-11-07 22:41:44 +01:00
{ " version " : " 10.0 " , " path " : " 17.0 " , " desc " : " Delphi 10 Seattle " } ,
2023-11-06 14:46:39 +01:00
{ " version " : " 10.1 " , " path " : " 18.0 " , " desc " : " Delphi 10.1 Berlin " } ,
{ " version " : " 10.2 " , " path " : " 19.0 " , " desc " : " Delphi 10.2 Tokyo " } ,
{ " version " : " 10.3 " , " path " : " 20.0 " , " desc " : " Delphi 10.3 Rio " } ,
{ " version " : " 10.4 " , " path " : " 21.0 " , " desc " : " Delphi 10.4 Sydney " } ,
2023-11-07 22:41:44 +01:00
{ " version " : " 11.0 " , " path " : " 22.0 " , " desc " : " Delphi 11 Alexandria " } ,
2023-11-06 14:46:39 +01:00
{ " version " : " 11.1 " , " path " : " 22.0 " , " desc " : " Delphi 11.1 Alexandria " } ,
{ " version " : " 11.2 " , " path " : " 22.0 " , " desc " : " Delphi 11.2 Alexandria " } ,
{ " version " : " 11.3 " , " path " : " 22.0 " , " desc " : " Delphi 11.3 Alexandria " } ,
2023-11-07 22:41:44 +01:00
{ " version " : " 12.0 " , " path " : " 23.0 " , " desc " : " Delphi 12 Athens " } ,
2023-11-06 14:46:39 +01:00
]
def get_delphi_projects_to_build ( which = " " ) :
2019-01-08 12:48:27 +01:00
projects = [ ]
2023-11-06 14:46:39 +01:00
delphi_version , _ = get_best_delphi_version_available ( )
dversion = " d " + delphi_version [ " version " ] . replace ( " . " , " " )
2020-04-07 10:37:33 +02:00
if not which or which == " core " :
projects + = glob . glob (
r " packages \ {dversion} \ *.groupproj " . format ( dversion = dversion )
)
2019-09-04 19:36:42 +02:00
projects + = glob . glob ( r " tools \ entitygenerator \ MVCAREntitiesGenerator.dproj " )
2020-04-07 10:37:33 +02:00
if not which or which == " tests " :
2019-01-08 12:48:27 +01:00
projects + = glob . glob ( r " unittests \ ** \ *.dproj " )
2020-04-07 10:37:33 +02:00
if not which or which == " samples " :
2019-01-08 12:48:27 +01:00
projects + = glob . glob ( r " samples \ ** \ *.dproj " )
2019-05-19 15:01:21 +02:00
projects + = glob . glob ( r " samples \ ** \ ** \ *.dproj " )
projects + = glob . glob ( r " samples \ ** \ ** \ ** \ *.dproj " )
2019-05-19 20:23:45 +02:00
return sorted ( projects )
2019-01-08 12:48:27 +01:00
2023-11-06 14:46:39 +01:00
def get_best_delphi_version_available ( ) - > ( dict , str ) :
global delphi_version
found = False
rsvars_path = None
i = len ( delphi_versions )
while ( not found ) and ( i > = 0 ) :
i - = 1
delphi_version = delphi_versions [ i ]
version_path = delphi_version [ " path " ]
rsvars_path = f " C: \\ Program Files (x86) \\ Embarcadero \\ Studio \\ { version_path } \\ bin \\ rsvars.bat "
if os . path . isfile ( rsvars_path ) :
found = True
else :
rsvars_path = f " D: \\ Program Files (x86) \\ Embarcadero \\ Studio \\ { version_path } \\ bin \\ rsvars.bat "
if os . path . isfile ( rsvars_path ) :
found = True
if found :
return delphi_version , rsvars_path
else :
raise Exception ( " Cannot find a Delphi compiler " )
2020-04-07 10:37:33 +02:00
def build_delphi_project (
2023-11-06 14:46:39 +01:00
ctx : context . Context , project_filename , config = " DEBUG " , platform = " Win32 "
2020-04-07 10:37:33 +02:00
) :
2023-11-06 14:46:39 +01:00
delphi_version , rsvars_path = get_best_delphi_version_available ( )
2023-11-07 22:41:44 +01:00
print ( ' \n BUILD WITH: ' + delphi_version [ " desc " ] )
2020-04-07 10:37:33 +02:00
cmdline = (
' " '
+ rsvars_path
+ ' " '
+ " & msbuild /t:Build /p:Config= "
+ config
2023-01-28 23:31:00 +01:00
+ f ' /p:Platform= { platform } " '
2020-04-07 10:37:33 +02:00
+ project_filename
+ ' " '
)
2021-03-04 14:29:13 +01:00
r = ctx . run ( cmdline , hide = True , warn = True )
if r . failed :
print ( r . stdout )
print ( r . stderr )
2023-11-06 14:46:39 +01:00
raise Exit ( " Build failed for " + delphi_version [ " desc " ] )
2019-01-08 12:48:27 +01:00
def zip_samples ( version ) :
global g_output_folder
2020-04-07 10:37:33 +02:00
cmdline = (
" 7z a "
+ g_output_folder
+ f " \\ .. \\ { version } _samples.zip -r -i@7ziplistfile.txt "
)
2019-01-08 12:48:27 +01:00
return subprocess . call ( cmdline , shell = True ) == 0
2019-01-08 15:15:53 +01:00
2019-01-08 12:48:27 +01:00
def create_zip ( ctx , version ) :
global g_output_folder
print ( " CREATING ZIP " )
2019-05-19 20:23:45 +02:00
archive_name = " .. \\ " + version + " .zip "
2019-01-08 12:48:27 +01:00
switches = " "
files_name = " * "
cmdline = f " .. \\ .. \\ 7z.exe a { switches } { archive_name } * "
print ( cmdline )
with ctx . cd ( g_output_folder ) :
ctx . run ( cmdline , hide = False )
def copy_sources ( ) :
global g_output_folder
os . makedirs ( g_output_folder + " \\ sources " , exist_ok = True )
os . makedirs ( g_output_folder + " \\ ideexpert " , exist_ok = True )
os . makedirs ( g_output_folder + " \\ packages " , exist_ok = True )
2019-09-04 19:36:42 +02:00
os . makedirs ( g_output_folder + " \\ tools " , exist_ok = True )
2019-01-08 12:48:27 +01:00
# copying main sources
print ( " Copying DMVCFramework Sources... " )
src = glob . glob ( " sources \\ *.pas " ) + glob . glob ( " sources \\ *.inc " )
for file in src :
print ( " Copying " + file + " to " + g_output_folder + " \\ sources " )
copy2 ( file , g_output_folder + " \\ sources \\ " )
2019-09-04 19:36:42 +02:00
# copying tools
2019-10-15 12:51:08 +02:00
print ( " Copying tools... " )
2023-11-06 14:46:39 +01:00
copytree ( " tools \\ entitygenerator " , g_output_folder + " \\ tools \\ entitygenerator " )
2019-09-04 19:36:42 +02:00
2019-01-08 12:48:27 +01:00
# copying ideexperts
print ( " Copying DMVCFramework IDEExpert... " )
2020-04-07 10:37:33 +02:00
src = (
glob . glob ( " ideexpert \\ *.pas " )
+ glob . glob ( " ideexpert \\ *.dfm " )
+ glob . glob ( " ideexpert \\ *.ico " )
+ glob . glob ( " ideexpert \\ *.bmp " )
)
2019-01-14 11:53:43 +01:00
2019-01-08 12:48:27 +01:00
for file in src :
print ( " Copying " + file + " to " + g_output_folder + " \\ ideexpert " )
copy2 ( file , g_output_folder + " \\ ideexpert \\ " )
2019-01-29 17:59:02 +01:00
files = [
" dmvcframeworkDTResource.rc " ,
" dmvcframework_group.groupproj " ,
" dmvcframeworkRT.dproj " ,
" dmvcframeworkRT.dpk " ,
" dmvcframeworkDT.dproj " ,
2020-04-07 10:37:33 +02:00
" dmvcframeworkDT.dpk " ,
2019-01-29 17:59:02 +01:00
]
2019-01-14 11:53:43 +01:00
2023-11-06 14:46:39 +01:00
folders = [ " d100 " , " d101 " , " d102 " , " d103 " , " d104 " , " d110 " , " d113 " ]
2019-01-08 12:48:27 +01:00
2019-01-29 17:59:02 +01:00
for folder in folders :
print ( f " Copying DMVCFramework Delphi { folder } packages... " )
for file in files :
os . makedirs ( g_output_folder + f " \\ packages \\ { folder } " , exist_ok = True )
2020-04-07 10:37:33 +02:00
copy2 (
rf " packages \ { folder } \ { file } " , g_output_folder + rf " \ packages \ { folder } "
)
2023-04-21 16:20:36 +02:00
# copy2(
# rf"packages\common_contains.inc", g_output_folder + rf"\packages"
# )
# copy2(
# rf"packages\common_defines.inc", g_output_folder + rf"\packages"
# )
# copy2(
# rf"packages\common_defines_design.inc", g_output_folder + rf"\packages"
# )
2019-01-08 12:48:27 +01:00
2019-01-29 17:59:02 +01:00
def copy_libs ( ctx ) :
2019-01-08 12:48:27 +01:00
global g_output_folder
2019-10-15 12:51:08 +02:00
# swagdoc
print ( " Copying libraries: SwagDoc... " )
curr_folder = g_output_folder + " \\ lib \\ swagdoc "
os . makedirs ( curr_folder , exist_ok = True )
if not ctx . run ( rf " xcopy lib \ swagdoc \ *.* { curr_folder } \ *.* /E /Y /R /V /F " ) :
raise Exception ( " Cannot copy SwagDoc " )
2019-01-08 12:48:27 +01:00
# loggerpro
print ( " Copying libraries: LoggerPro... " )
curr_folder = g_output_folder + " \\ lib \\ loggerpro "
os . makedirs ( curr_folder , exist_ok = True )
2019-01-29 17:59:02 +01:00
if not ctx . run ( rf " xcopy lib \ loggerpro \ *.* { curr_folder } \ *.* /E /Y /R /V /F " ) :
raise Exception ( " Cannot copy loggerpro " )
2019-01-08 12:48:27 +01:00
2019-10-15 12:51:08 +02:00
# dmustache
2019-01-08 12:48:27 +01:00
print ( " Copying libraries: dmustache... " )
curr_folder = g_output_folder + " \\ lib \\ dmustache "
os . makedirs ( curr_folder , exist_ok = True )
2019-01-29 17:59:02 +01:00
if not ctx . run ( rf " xcopy lib \ dmustache \ *.* { curr_folder } \ *.* /E /Y /R /V /F " ) :
raise Exception ( " Cannot copy dmustache " )
2019-01-08 12:48:27 +01:00
2019-01-08 15:15:53 +01:00
def printkv ( key , value ) :
2023-11-06 14:46:39 +01:00
print ( Fore . RESET + key + " : " + Fore . GREEN + value . rjust ( 60 ) + Fore . RESET )
2019-01-08 15:15:53 +01:00
2019-01-08 12:48:27 +01:00
def init_build ( version ) :
""" Required by all tasks """
global g_version
global g_output_folder
global g_releases_path
g_version = version
g_output_folder = g_releases_path + " \\ " + g_version
2019-05-19 20:23:45 +02:00
print ( )
print ( Fore . RESET + Fore . RED + " * " * 80 )
print ( Fore . RESET + Fore . RED + " BUILD VERSION: " + g_version + Fore . RESET )
print ( Fore . RESET + Fore . RED + " OUTPUT PATH : " + g_output_folder + Fore . RESET )
2020-04-07 10:37:33 +02:00
print ( Fore . RESET + Fore . RED + " * " * 80 )
2019-01-29 17:59:02 +01:00
2019-01-08 12:48:27 +01:00
rmtree ( g_output_folder , True )
os . makedirs ( g_output_folder , exist_ok = True )
f = open ( g_output_folder + " \\ version.txt " , " w " )
f . write ( " VERSION " + g_version + " \n " )
f . write ( " BUILD DATETIME " + datetime . now ( ) . isoformat ( ) + " \n " )
f . close ( )
copy2 ( " README.md " , g_output_folder )
copy2 ( " 3_0_0_breaking_changes.md " , g_output_folder )
copy2 ( " 3_1_0_breaking_changes.md " , g_output_folder )
2019-10-15 12:51:08 +02:00
copy2 ( " 3_2_0_breaking_changes.md " , g_output_folder )
2019-01-08 12:48:27 +01:00
copy2 ( " License.txt " , g_output_folder )
2020-04-07 10:37:33 +02:00
def build_delphi_project_list (
2023-11-06 14:46:39 +01:00
ctx , projects , config = " DEBUG " , filter = " "
2020-04-07 10:37:33 +02:00
) :
2019-01-08 12:48:27 +01:00
ret = True
for delphi_project in projects :
if filter and ( not filter in delphi_project ) :
print ( f " Skipped { os . path . basename ( delphi_project ) } " )
continue
msg = f " Building: { os . path . basename ( delphi_project ) } ( { config } ) "
2020-04-07 10:37:33 +02:00
print ( Fore . RESET + msg . ljust ( 90 , " . " ) , end = " " )
2021-03-04 14:29:13 +01:00
try :
2023-11-06 14:46:39 +01:00
build_delphi_project ( ctx , delphi_project , " DEBUG " )
2020-04-07 10:37:33 +02:00
print ( Fore . GREEN + " OK " + Fore . RESET )
2021-03-04 14:29:13 +01:00
except Exception as e :
2019-01-08 12:48:27 +01:00
print ( Fore . RED + " \n \n BUILD ERROR " )
2021-03-04 14:29:13 +01:00
print ( Fore . RESET )
print ( e )
# if res.ok:
# print(Fore.GREEN + "OK" + Fore.RESET)
# else:
# ret = False
# print(Fore.RED + "\n\nBUILD ERROR")
# print(Fore.RESET + res.stdout)
# print("\n")
2019-01-08 12:48:27 +01:00
return ret
2019-01-29 17:59:02 +01:00
@task
2020-04-07 10:37:33 +02:00
def clean ( ctx , folder = None ) :
2019-01-29 17:59:02 +01:00
global g_output_folder
import os
import glob
2020-04-07 10:37:33 +02:00
if folder is None :
folder = g_output_folder
print ( f " Cleaning folder { folder } " )
output = pathlib . Path ( folder )
2019-01-29 17:59:02 +01:00
to_delete = [ ]
2020-04-07 10:37:33 +02:00
to_delete + = glob . glob ( folder + r " \ ** \ *.exe " , recursive = True )
to_delete + = glob . glob ( folder + r " \ ** \ *.dcu " , recursive = True )
to_delete + = glob . glob ( folder + r " \ ** \ *.stat " , recursive = True )
to_delete + = glob . glob ( folder + r " \ ** \ *.res " , recursive = True )
to_delete + = glob . glob ( folder + r " \ ** \ *.map " , recursive = True )
to_delete + = glob . glob ( folder + r " \ ** \ *.~* " , recursive = True )
to_delete + = glob . glob ( folder + r " \ ** \ *.rsm " , recursive = True )
to_delete + = glob . glob ( folder + r " \ ** \ *.drc " , recursive = True )
to_delete + = glob . glob ( folder + r " \ ** \ *.log " , recursive = True )
to_delete + = glob . glob ( folder + r " \ ** \ *.local " , recursive = True )
to_delete + = glob . glob ( folder + r " \ ** \ *.gitignore " , recursive = True )
to_delete + = glob . glob ( folder + r " \ ** \ *.gitattributes " , recursive = True )
2019-01-29 17:59:02 +01:00
for f in to_delete :
2020-04-07 10:37:33 +02:00
print ( f " Deleting { f } " )
2019-01-29 17:59:02 +01:00
os . remove ( f )
2020-04-07 10:37:33 +02:00
rmtree ( folder + r " \ lib \ loggerpro \ Win32 " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d100 \ __history " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d100 \ Win32 \ Debug " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d101 \ __history " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d101 \ Win32 \ Debug " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d102 \ __history " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d102 \ Win32 \ Debug " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d103 \ __history " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d103 \ Win32 \ Debug " , True )
2020-05-28 22:35:45 +02:00
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d104 \ __history " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d104 \ Win32 \ Debug " , True )
2022-09-15 09:09:33 +02:00
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d110 \ __history " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d110 \ Win32 \ Debug " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d111 \ __history " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d111 \ Win32 \ Debug " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d112 \ __history " , True )
rmtree ( folder + r " \ lib \ loggerpro \ packages \ d112 \ Win32 \ Debug " , True )
2020-04-07 10:37:33 +02:00
rmtree ( folder + r " \ lib \ dmustache \ .git " , True )
rmtree ( folder + r " \ lib \ swagdoc \ lib " , True )
rmtree ( folder + r " \ lib \ swagdoc \ deploy " , True )
rmtree ( folder + r " \ lib \ swagdoc \ demos " , True )
2021-03-04 14:29:13 +01:00
2020-05-02 17:06:59 +02:00
@task ( )
2023-11-27 11:17:18 +01:00
def tests32 ( ctx ) :
2023-01-28 23:31:00 +01:00
""" Builds and execute the unit tests """
import os
apppath = os . path . dirname ( os . path . realpath ( __file__ ) )
res = True
testclient = r " unittests \ general \ Several \ DMVCFrameworkTests.dproj "
testserver = r " unittests \ general \ TestServer \ TestServer.dproj "
print ( " \n Building Unit Test client " )
2023-11-06 14:46:39 +01:00
build_delphi_project (
2023-11-27 11:17:18 +01:00
ctx , testclient , config = " CI " , platform = " Win32 "
2023-11-06 14:46:39 +01:00
)
2023-01-28 23:31:00 +01:00
print ( " \n Building Test Server " )
2023-11-06 14:46:39 +01:00
build_delphi_project (
2023-11-27 11:17:18 +01:00
ctx , testserver , config = " CI " , platform = " Win32 "
2023-11-06 14:46:39 +01:00
)
2023-01-28 23:31:00 +01:00
# import subprocess
# subprocess.run([r"unittests\general\TestServer\Win32\Debug\TestServer.exe"])
# os.spawnl(os.P_NOWAIT, r"unittests\general\TestServer\Win32\Debug\TestServer.exe")
import subprocess
print ( " \n Executing tests... " )
subprocess . Popen ( [ r " unittests \ general \ TestServer \ bin \ TestServer.exe " ] , shell = True )
2023-09-22 09:43:35 +02:00
r = None
try :
r = subprocess . run ( [ r " unittests \ general \ Several \ bin32 \ DMVCFrameworkTests.exe " ] )
if r . returncode != 0 :
return Exit ( " Cannot run unit test client: \n " + str ( r . stdout ) )
finally :
subprocess . run ( [ " taskkill " , " /f " , " /im " , " TestServer.exe " ] )
2023-01-28 23:31:00 +01:00
if r . returncode > 0 :
print ( r )
print ( " Unit Tests Failed " )
return Exit ( " Unit tests failed " )
@task ( )
2023-11-06 14:46:39 +01:00
def tests64 ( ctx ) :
2020-05-02 17:06:59 +02:00
""" Builds and execute the unit tests """
import os
apppath = os . path . dirname ( os . path . realpath ( __file__ ) )
res = True
testclient = r " unittests \ general \ Several \ DMVCFrameworkTests.dproj "
testserver = r " unittests \ general \ TestServer \ TestServer.dproj "
print ( " \n Building Unit Test client " )
2023-11-06 14:46:39 +01:00
build_delphi_project (
ctx , testclient , config = " CI " , platform = " Win64 "
)
2020-05-02 17:06:59 +02:00
print ( " \n Building Test Server " )
2023-11-06 14:46:39 +01:00
build_delphi_project (
ctx , testserver , config = " CI " , platform = " Win64 "
)
2020-05-02 17:06:59 +02:00
# import subprocess
# subprocess.run([r"unittests\general\TestServer\Win32\Debug\TestServer.exe"])
# os.spawnl(os.P_NOWAIT, r"unittests\general\TestServer\Win32\Debug\TestServer.exe")
import subprocess
print ( " \n Executing tests... " )
2022-03-25 10:49:12 +01:00
subprocess . Popen ( [ r " unittests \ general \ TestServer \ bin \ TestServer.exe " ] , shell = True )
2023-09-22 09:43:35 +02:00
r = None
try :
r = subprocess . run ( [ r " unittests \ general \ Several \ bin64 \ DMVCFrameworkTests.exe " ] )
if r . returncode != 0 :
return Exit ( " Cannot run unit test client: \n " + str ( r . stdout ) )
finally :
subprocess . run ( [ " taskkill " , " /f " , " /im " , " TestServer.exe " ] )
2020-05-02 17:06:59 +02:00
if r . returncode > 0 :
print ( r )
print ( " Unit Tests Failed " )
return Exit ( " Unit tests failed " )
2020-04-07 10:37:33 +02:00
2019-01-29 17:59:02 +01:00
2023-01-28 23:31:00 +01:00
@task ( pre = [ tests32 , tests64 ] )
2023-11-06 14:46:39 +01:00
def tests ( ctx ) :
2023-01-28 23:31:00 +01:00
pass
2023-11-06 14:46:39 +01:00
2023-04-21 16:20:36 +02:00
@task ( )
2020-04-07 10:37:33 +02:00
def release (
2023-11-06 14:46:39 +01:00
ctx ,
version = " DEBUG " ,
skip_build = False ,
skip_tests = False ,
2020-04-07 10:37:33 +02:00
) :
2019-01-14 11:53:43 +01:00
""" Builds all the projects, executes integration tests and prepare the release """
2019-01-08 12:48:27 +01:00
init_build ( version )
2023-04-21 16:20:36 +02:00
2023-11-06 14:46:39 +01:00
if not skip_tests :
tests ( ctx )
2019-01-08 12:48:27 +01:00
if not skip_build :
2023-11-06 14:46:39 +01:00
delphi_projects = get_delphi_projects_to_build ( " " )
2020-04-07 10:37:33 +02:00
if not build_delphi_project_list (
2023-11-06 14:46:39 +01:00
ctx , delphi_projects , version , " "
2020-04-07 10:37:33 +02:00
) :
return False # fails build
2019-10-15 12:51:08 +02:00
print ( Fore . RESET )
2019-01-08 12:48:27 +01:00
copy_sources ( )
2019-01-29 17:59:02 +01:00
copy_libs ( ctx )
clean ( ctx )
2019-01-08 12:48:27 +01:00
zip_samples ( version )
create_zip ( ctx , version )
2019-01-08 15:15:53 +01:00
2019-01-08 12:48:27 +01:00
@task
2020-04-07 10:37:33 +02:00
def build_samples (
2023-11-06 14:46:39 +01:00
ctx , version = " DEBUG " , filter = " "
2020-04-07 10:37:33 +02:00
) :
2019-01-08 12:48:27 +01:00
""" Builds samples """
init_build ( version )
2023-11-06 14:46:39 +01:00
delphi_projects = get_delphi_projects_to_build ( " samples " )
2020-04-07 10:37:33 +02:00
return build_delphi_project_list (
2023-11-06 14:46:39 +01:00
ctx , delphi_projects , version , filter
2020-04-07 10:37:33 +02:00
)
2019-01-08 12:48:27 +01:00
2023-02-02 19:14:34 +01:00
@task ( post = [ ] )
2023-11-06 14:46:39 +01:00
def build_core ( ctx , version = " DEBUG " ) :
2019-01-14 11:53:43 +01:00
""" Builds core packages extensions """
2019-01-08 12:48:27 +01:00
init_build ( version )
2023-11-06 14:46:39 +01:00
delphi_projects = get_delphi_projects_to_build ( " core " )
ret = build_delphi_project_list ( ctx , delphi_projects , version , " " )
2020-04-07 10:37:33 +02:00
if not ret :
raise Exit ( " Build failed " )
2020-02-03 10:51:40 +01:00
def parse_template ( tmpl : List [ str ] ) :
main_tmpl = [ ]
intf_tmpl = [ ]
impl_tmpl = [ ]
2020-04-07 10:37:33 +02:00
state = " verbatim "
2020-02-03 10:51:40 +01:00
for row in tmpl :
2020-04-07 10:37:33 +02:00
if row . upper ( ) . strip ( ) == " ///INTERFACE.BEGIN " :
state = " parsing.interface "
2020-02-03 10:51:40 +01:00
continue
2020-04-07 10:37:33 +02:00
if row . upper ( ) . strip ( ) == " ///IMPLEMENTATION.BEGIN " :
state = " parsing.implementation "
2020-02-03 10:51:40 +01:00
continue
2020-04-07 10:37:33 +02:00
if row . upper ( ) . strip ( ) in [ " ///INTERFACE.END " , " ///IMPLEMENTATION.END " ] :
if state == " parsing.interface " :
main_tmpl . append ( " $INTERFACE$ " )
2023-11-06 14:46:39 +01:00
if state == " parsing.implementation " :
2020-04-07 10:37:33 +02:00
main_tmpl . append ( " $IMPLEMENTATION$ " )
state = " verbatim "
2020-02-03 10:51:40 +01:00
continue
2020-04-07 10:37:33 +02:00
if state == " parsing.interface " :
2020-02-03 10:51:40 +01:00
intf_tmpl . append ( row )
2020-04-07 10:37:33 +02:00
elif state == " parsing.implementation " :
2020-02-03 10:51:40 +01:00
impl_tmpl . append ( row )
2020-04-07 10:37:33 +02:00
elif state == " verbatim " :
2020-02-03 10:51:40 +01:00
main_tmpl . append ( row )
return main_tmpl , intf_tmpl , impl_tmpl
2020-04-07 10:37:33 +02:00
2020-02-03 10:51:40 +01:00
@task
def generate_nullables ( ctx ) :
import pathlib
2020-04-07 10:37:33 +02:00
2020-02-03 10:51:40 +01:00
src_folder = pathlib . Path ( __file__ ) . parent . joinpath ( " sources " )
template_unitname = src_folder . joinpath ( " MVCFramework.Nullables.pas.template " )
2020-04-07 10:37:33 +02:00
output_unitname = src_folder . joinpath ( " MVCFramework.Nullables.pas " )
2020-02-03 10:51:40 +01:00
2020-04-07 10:37:33 +02:00
with open ( template_unitname , " r " ) as f :
2020-02-03 10:51:40 +01:00
rows = f . readlines ( )
main_tmpl , intf_tmpl , impl_tmpl = parse_template ( rows )
delphi_types = [
2023-11-06 14:46:39 +01:00
[
" String " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and \n \t (LeftValue.Value = RightValue.Value)) " ,
] ,
[
" Currency " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and \n \t (LeftValue.Value = RightValue.Value)) " ,
] ,
[
" Boolean " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and \n \t (LeftValue.Value = RightValue.Value)) " ,
] ,
[
" TDate " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and \n \t (DateToISODate(LeftValue.Value) = DateToISODate(RightValue.Value))) " ,
] ,
[
" TTime " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and \n \t (TimeToISOTime(LeftValue.Value) = TimeToISOTime(RightValue.Value))) " ,
] ,
[
" TDateTime " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and \n \t (DateTimeToISOTimeStamp(LeftValue.Value) = DateTimeToISOTimeStamp(RightValue.Value))) " ,
] ,
[
" Single " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and \n \t SameValue(LeftValue.Value, RightValue.Value, 0.000001)) " ,
] ,
[
" Double " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and \n \t SameValue(LeftValue.Value, RightValue.Value, 0.000000001)) " ,
] ,
[
" Extended " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and \n \t SameValue(LeftValue.Value, RightValue.Value, 0.000000001)) " ,
] ,
[
" Int16 " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and (LeftValue.Value = RightValue.Value)) " ,
] ,
[
" UInt16 " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and (LeftValue.Value = RightValue.Value)) " ,
] ,
[
" Int32 " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and (LeftValue.Value = RightValue.Value)) " ,
] ,
[
" UInt32 " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and (LeftValue.Value = RightValue.Value)) " ,
] ,
[
" Int64 " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and (LeftValue.Value = RightValue.Value)) " ,
] ,
[
" UInt64 " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and (LeftValue.Value = RightValue.Value)) " ,
] ,
[
" TGUID " ,
" (LeftValue.IsNull and RightValue.IsNull) or ((LeftValue.HasValue and RightValue.HasValue) and (LeftValue.Value = RightValue.Value)) " ,
] ,
2020-04-07 10:37:33 +02:00
]
2020-02-03 10:51:40 +01:00
str_main_tmpl = " " . join ( main_tmpl )
str_intf_tmpl = " " . join ( intf_tmpl )
str_impl_tmpl = " " . join ( impl_tmpl )
intf_out = " "
impl_out = " "
2022-08-01 19:11:42 +02:00
enum_declaration = [ " ntInvalidNullableType " ]
enum_detect_line = [ ]
2023-01-28 23:31:00 +01:00
for delphi_type , type_compare in delphi_types :
2023-11-06 14:46:39 +01:00
enum_declaration . append ( " ntNullable " + delphi_type )
enum_detect_line . append (
f " if aTypeInfo = TypeInfo(Nullable { delphi_type } ) then \n Exit(ntNullable { delphi_type } ); "
)
2022-08-01 19:11:42 +02:00
2020-04-07 10:37:33 +02:00
intf_out + = (
f " //************************** \n // ** Nullable { delphi_type } \n //************************** \n \n "
+ str_intf_tmpl . replace ( " $TYPE$ " , delphi_type )
)
2023-11-06 14:46:39 +01:00
impl_out + = (
str_impl_tmpl . replace ( " $TYPE$ " , delphi_type ) . replace (
" $COMPARE$ " , type_compare
)
+ " \n "
)
2020-02-03 10:51:40 +01:00
2023-11-06 14:46:39 +01:00
enum_declaration = (
" TNullableType = ( \n " + " \n , " . join ( enum_declaration ) + " ); \n \n "
)
2022-08-01 19:11:42 +02:00
enum_detect_function = [ ]
2023-11-06 14:46:39 +01:00
enum_detect_function . append (
" function GetNullableType(const aTypeInfo: PTypeInfo): TNullableType; "
)
2022-08-01 19:11:42 +02:00
enum_detect_function . append ( " begin " )
2023-11-06 14:46:39 +01:00
enum_detect_function . extend ( enum_detect_line )
2022-08-01 19:11:42 +02:00
enum_detect_function . append ( " Result := ntInvalidNullableType; " )
enum_detect_function . append ( " end; " )
intf_out + = enum_declaration + " \n "
intf_out + = enum_detect_function [ 0 ] + " \n "
impl_out + = " \n " . join ( enum_detect_function ) + " \n "
2023-11-06 14:46:39 +01:00
str_main_tmpl = (
str_main_tmpl . replace ( " $INTERFACE$ " , intf_out ) . replace (
" $IMPLEMENTATION$ " , impl_out
)
2022-08-01 19:11:42 +02:00
+ " \n "
2023-11-06 14:46:39 +01:00
)
2020-02-03 10:51:40 +01:00
2020-04-07 10:37:33 +02:00
with open ( output_unitname , " w " ) as f :
2020-02-03 10:51:40 +01:00
f . writelines ( str_main_tmpl )
2020-04-07 10:37:33 +02:00
with open ( src_folder . joinpath ( " main.out.txt " ) , " w " ) as f :
2020-02-03 10:51:40 +01:00
f . writelines ( main_tmpl )
2020-04-07 10:37:33 +02:00
with open ( src_folder . joinpath ( " interface.out.txt " ) , " w " ) as f :
2020-02-03 10:51:40 +01:00
f . writelines ( intf_tmpl )
2020-04-07 10:37:33 +02:00
with open ( src_folder . joinpath ( " implementation.out.txt " ) , " w " ) as f :
2020-02-03 10:51:40 +01:00
f . writelines ( impl_tmpl )