diff --git a/corePython/buildList.py b/corePython/buildList.py index 416c73d..16ee2d1 100644 --- a/corePython/buildList.py +++ b/corePython/buildList.py @@ -1,30 +1,36 @@ #!/usr/bin/python import debug import module +import target_Linux +import host availlable=[] -def AddModule(name): +def AddModule(name, type): global availlable - availlable.append([name,"Module"]) + if type=="BINARY": + availlable.append([name,"Module", "bin"]) + else: + availlable.append([name,"Module", "other"]) def AddPackage(name): global availlable - availlable.append([name,"Package"]) + availlable.append([name,"Package", "pkg"]) def Build(name): if name == "all": debug.info("Build all") for elem in availlable: if elem[1] == "Module": - module.Build(elem[0]) + if elem[2] == "bin": + module.Build(elem[0], GetCurrentTarget()) else: debug.error("TODO ... Build package '" + elem[0] + "'") elif name == "clean": debug.info("Clean all") for elem in availlable: if elem[1] == "Module": - module.Clean(elem[0]) + module.Clean(elem[0], GetCurrentTarget()) else: debug.error("TODO ... Clean package '" + elem[0] + "'") else: @@ -36,7 +42,7 @@ def Build(name): if elem[0] == cleanName: if elem[1] == "Module": debug.info("Clean module '" + cleanName + "'") - module.Clean(cleanName) + module.Clean(cleanName, GetCurrentTarget()) else: debug.info("Clean package '" + cleanName + "'") debug.error("TODO ... Clean package '" + cleanName + "'") @@ -49,7 +55,7 @@ def Build(name): if elem[0] == name: if elem[1] == "Module": debug.info("Build module '" + name + "'") - module.Build(name) + module.Build(name, GetCurrentTarget()) else: debug.info("Build package '" + name + "'") debug.error("TODO ... Build package '" + cleanName + "'") @@ -58,4 +64,26 @@ def Build(name): debug.error("not know module name : '" + name + "' to build it") +currentTarget=None + +def SetTarget(name): + global currentTarget + if name=="Linux": + currentTarget = target_Linux.Target() + elif name=="Windows": + debug.error("TODO : create target type :'" + name + "'") + elif name=="MacOs": + debug.error("TODO : create target type :'" + name + "'") + elif name=="Android": + debug.error("TODO : create target type :'" + name + "'") + else: + debug.error("Unknow target type :'" + name + "'") + + +def GetCurrentTarget(): + global currentTarget + if currentTarget==None: + SetTarget(host.OS) + + return currentTarget diff --git a/corePython/buildTools.py b/corePython/buildTools.py index ea68c96..af12aac 100644 --- a/corePython/buildTools.py +++ b/corePython/buildTools.py @@ -1,5 +1,10 @@ #!/usr/bin/python import os +import shutil +import errno +import debug +import fnmatch + """ @@ -32,6 +37,8 @@ def ListToStr(list): return result def AddPrefix(prefix,list): + if type(list) == type(None): + return "" if type(list) == type(str()): return prefix+list else: @@ -42,3 +49,25 @@ def AddPrefix(prefix,list): for elem in list: result.append(prefix+elem) return result + +def CopyFile(src, dst): + if os.path.exists(dst): + if os.path.getmtime(dst) > os.path.getmtime(src): + return + debug.printElement("copy file", src, "==>", dst) + CreateDirectoryOfFile(dst) + shutil.copyfile(src, dst) + + +def CopyAnything(src, dst): + tmpPath = os.path.dirname(os.path.realpath(src)) + tmpRule = os.path.basename(src) + for root, dirnames, filenames in os.walk(tmpPath): + tmpList = filenames + if len(tmpRule)>0: + tmpList = fnmatch.filter(filenames, tmpRule) + # Import the module : + for cycleFile in tmpList: + #for cycleFile in filenames: + #debug.info("Might copy : '" + tmpPath+cycleFile + "' ==> '" + dst + "'") + CopyFile(tmpPath+"/"+cycleFile,dst+"/"+cycleFile) diff --git a/corePython/debug.py b/corePython/debug.py index 6147c6b..579e132 100644 --- a/corePython/debug.py +++ b/corePython/debug.py @@ -3,6 +3,14 @@ debugLevel=3 debugColor=False +color_default= "" +color_red = "" +color_green = "" +color_yellow = "" +color_blue = "" +color_purple = "" +color_cyan = "" + def SetLevel(id): global debugLevel debugLevel = id @@ -11,26 +19,43 @@ def SetLevel(id): def EnableColor(): global debugColor debugColor = True + global color_default + color_default= "\033[00m" + global color_red + color_red = "\033[31m" + global color_green + color_green = "\033[32m" + global color_yellow + color_yellow = "\033[33m" + global color_blue + color_blue = "\033[34m" + global color_purple + color_purple = "\033[35m" + global color_cyan + color_cyan = "\033[36m" def verbose(input): if debugLevel >= 5: - print input + print color_blue + input + color_default def debug(input): if debugLevel >= 4: - print input + print color_green + input + color_default def info(input): if debugLevel >= 3: - print input + print input + color_default def warning(input): if debugLevel >= 2: - print "WARNING : " + input + print color_purple + "[WARNING] " + input + color_default def error(input): if debugLevel >= 1: - print "ERROR : " + input - raise "error happend" - + print color_red + "[ERROR] " + input + color_default + exit(-1) + #raise "error happend" +def printElement(type, lib, dir, name): + if debugLevel >= 3: + print color_cyan + type + color_default + " : " + color_yellow + lib + color_default + " " + dir + " " + color_blue + name + color_default diff --git a/corePython/host.py b/corePython/host.py index 940c750..ec1d6a0 100755 --- a/corePython/host.py +++ b/corePython/host.py @@ -3,7 +3,6 @@ import platform import debug # print os.name # ==> 'posix' - if platform.system() == "Linux": OS = "Linux" elif platform.system() == "Windows": diff --git a/corePython/module.py b/corePython/module.py index f3d793e..b313168 100755 --- a/corePython/module.py +++ b/corePython/module.py @@ -8,9 +8,14 @@ import host import buildTools import debug import buildList -import target_Linux - +import heritage +def RunCommand(cmdLine): + debug.debug(cmdLine) + ret = os.system(cmdLine) + if ret != 0: + #print "result val = " + str(ret) + debug.error("can not compile file ... ") """ """ @@ -49,6 +54,7 @@ class module: self.flags_m=[] self.flags_mm=[] self.flags_s=[] + self.flags_ar=[] # sources list: self.src=[] # copy files and folders: @@ -67,13 +73,15 @@ class module: self.originFile = file; self.originFolder = buildTools.GetCurrentPath(self.originFile) self.name=moduleName + self.localHeritage = heritage.heritage(self) ############################################################################### ## Commands for running gcc to compile a m++ file. ############################################################################### - def Compile_mm_to_o(self, src, dst): + def Compile_mm_to_o(self, file, target, depancy): + # TODO : Check depedency ... buildTools.CreateDirectoryOfFile(dst) - debug.info("m++: " + self.name + " <== " + src) + debug.printElement("m++", self.name, "<==", file) """ cmdLine= $(TARGET_CXX) \ -o " + dst + " \ @@ -86,12 +94,15 @@ class module: "-x objective-c" + src """ + return tmpList[1] + ############################################################################### ## Commands for running gcc to compile a m file. ############################################################################### - def Compile_m_to_o(self, src, dst): + def Compile_m_to_o(self, file, target, depancy): + # TODO : Check depedency ... buildTools.CreateDirectoryOfFile(dst) - debug.info("m: " + self.name + " <== " + src) + debug.printElement("m", self.name, "<==", file) """ $(TARGET_CC) \ -o $@ \ @@ -105,13 +116,33 @@ class module: -x objective-c \ $(call path-from-top,$<) """ + return tmpList[1] ############################################################################### ## Commands for running gcc to compile a C++ file. ############################################################################### - def Compile_xx_to_o(self, src, dst): - buildTools.CreateDirectoryOfFile(dst) - debug.info("c++: " + self.name + " <== " + src) + def Compile_xx_to_o(self, file, target, depancy): + tmpList = target.GenerateFile(self.name,self.originFolder,file,"obj") + # TODO : Check depedency ... + if os.path.exists(tmpList[1]): + if os.path.getmtime(tmpList[1]) > os.path.getmtime(tmpList[0]): + return tmpList[1] + buildTools.CreateDirectoryOfFile(tmpList[1]) + debug.printElement("c++", self.name, "<==", file) + cmdLine=buildTools.ListToStr([ + target.xx, + "-o", tmpList[1] , + buildTools.AddPrefix("-I",self.export_path), + buildTools.AddPrefix("-I",self.local_path), + buildTools.AddPrefix("-I",depancy.path), + target.global_flags_cc, + target.global_flags_xx, + depancy.flags_cc, + depancy.flags_xx, + self.flags_cc, + " -c -MMD -MP -g ", + tmpList[0]]) + RunCommand(cmdLine) """ $(TARGET_CXX) \ -o $@ \ @@ -124,27 +155,32 @@ class module: -c -MMD -MP -g \ $(call path-from-top,$<) """ + return tmpList[1] ############################################################################### ## Commands for running gcc to compile a C file. ############################################################################### - def Compile_cc_to_o(self, src, dst): - buildTools.CreateDirectoryOfFile(dst) - debug.info("c: " + self.name + " <== " + src) + def Compile_cc_to_o(self, file, target, depancy): + tmpList = target.GenerateFile(self.name,self.originFolder,file,"obj") + # TODO : Check depedency ... + if os.path.exists(tmpList[1]): + if os.path.getmtime(tmpList[1]) > os.path.getmtime(tmpList[0]): + return tmpList[1] + buildTools.CreateDirectoryOfFile(tmpList[1]) + debug.printElement("c", self.name, "<==", file) cmdLine=buildTools.ListToStr([ - target_Linux.TARGET_CC, - "-o", dst , + target.cc, + "-o", tmpList[1], buildTools.AddPrefix("-I",self.export_path), buildTools.AddPrefix("-I",self.local_path), + buildTools.AddPrefix("-I",depancy.path), + target.global_flags_cc, + depancy.flags_cc, self.flags_cc, " -c -MMD -MP -g ", - src]) - debug.debug(cmdLine) - ret = os.system(cmdLine) - print "result val = " + str(ret) - if ret != 0: - debug.error("can not compile file : " + src) + tmpList[0]]) + RunCommand(cmdLine) """ $(TARGET_CC) \ -o $@ \ @@ -157,28 +193,48 @@ class module: -c -MMD -MP -g \ $(call path-from-top,$<) """ + return tmpList[1] ############################################################################### ## Commands for running ar. ############################################################################### - def Link_to_a(self, src, dst): - buildTools.CreateDirectoryOfFile(dst) - debug.info("StaticLib: " + self.name + " ==> " + dst) + def Link_to_a(self, file, target, depancy): + tmpList = target.GenerateFile(self.name,self.originFolder,file,"lib-static") + # TODO : Check depedency ... + buildTools.CreateDirectoryOfFile(tmpList[1]) + debug.printElement("StaticLib", self.name, "==>", tmpList[1]) # explicitly remove the destination to prevent error ... - os.remove(dst) + if os.path.exists(tmpList[1]) and os.path.isfile(tmpList[1]): + os.remove(tmpList[1]) #$(Q)$(TARGET_AR) $(TARGET_GLOBAL_ARFLAGS) $(PRIVATE_ARFLAGS) $@ $(PRIVATE_ALL_OBJECTS) + cmdLine=buildTools.ListToStr([ + target.ar, + target.global_flags_ar, + self.flags_ar, + tmpList[1], + tmpList[0], + depancy.src]) + RunCommand(cmdLine) #$(Q)$(TARGET_RANLIB) $@ + cmdLine=buildTools.ListToStr([ + target.ranlib, + tmpList[1] ]) + RunCommand(cmdLine) + return tmpList[1] ############################################################################### ## Commands for running gcc to link a shared library. ############################################################################### - def Link_to_so(self, src, dst): - buildTools.CreateDirectoryOfFile(dst) - debug.info("SharedLib: " + self.name + " ==> " + dst) + def Link_to_so(self, file, target, depancy): + tmpList = target.GenerateFile(self.name,self.originFolder,file,"lib-shared") + # TODO : Check depedency ... + buildTools.CreateDirectoryOfFile(tmpList[1]) + debug.error("SharedLib")# + self.name + " ==> " + dst) + #debug.printElement("SharedLib", self.name, "==>", tmpList[1]) """$(Q)$(TARGET_CXX) \ -o $@ \ $(TARGET_GLOBAL_LDFLAGS_SHARED) \ @@ -202,9 +258,21 @@ class module: ############################################################################### ## Commands for running gcc to link an executable. ############################################################################### - def Link_to_bin(self, src, dst): - buildTools.CreateDirectoryOfFile(dst) - debug.info("Executable: " + self.name + " ==> " + dst) + def Link_to_bin(self, file, target, depancy): + tmpList = target.GenerateFile(self.name,self.originFolder,file,"bin") + # TODO : Check depedency ... + buildTools.CreateDirectoryOfFile(tmpList[1]) + debug.printElement("Executable", self.name, "==>", tmpList[1]) + #$(Q)$(TARGET_AR) $(TARGET_GLOBAL_ARFLAGS) $(PRIVATE_ARFLAGS) $@ $(PRIVATE_ALL_OBJECTS) + cmdLine=buildTools.ListToStr([ + target.xx, + "-o", tmpList[1], + tmpList[0], + depancy.src, + self.flags_ld, + depancy.flags_ld, + target.global_flags_ld]) + RunCommand(cmdLine) """ $(TARGET_CXX) \ -o $@ \ @@ -225,39 +293,84 @@ class module: """ #$(call strip-executable) - + ############################################################################### + ## Commands for copying files + ############################################################################### + def files_to_staging(self, target, binaryName): + baseFolder = target.GetStagingFolder(binaryName) + for element in self.files: + debug.verbose("Might copy file : " + element[0] + " ==> " + element[1]) + buildTools.CopyFile(self.originFolder+"/"+element[0], baseFolder+"/"+element[1]) + + ############################################################################### + ## Commands for copying files + ############################################################################### + def folders_to_staging(self, target, binaryName): + baseFolder = target.GetStagingFolder(binaryName) + for element in self.folders: + debug.verbose("Might copy folder : " + element[0] + "==>" + element[1]) + buildTools.CopyAnything(self.originFolder+"/"+element[0], baseFolder+"/"+element[1]) + # call here to build the module - def Build(self): + def Build(self, target): # ckeck if not previously build - if self.isBuild==True: - return + if target.IsModuleBuild(self.name)==True: + return self.localHeritage # build dependency befor + listSubFileNeededToBuild = [] + subHeritage = heritage.heritage(None) for dep in self.depends: - Build(dep) + inherit = Build(dep, target) + # add at the heritage list : + subHeritage.AddSub(inherit) + # build local sources for file in self.src: - debug.info(" " + self.name + " <== " + file); + #debug.info(" " + self.name + " <== " + file); fileExt = file.split(".")[-1] if fileExt == "c" or fileExt == "C": - source = self.originFolder + "/" + file - destination = buildTools.GetRunFolder() + "/out/test/build/" + file + ".o" - print source - print destination - self.Compile_cc_to_o(source, destination) + resFile = self.Compile_cc_to_o(file, target, subHeritage) + listSubFileNeededToBuild.append(resFile) + elif fileExt == "cpp" or fileExt == "CPP" or fileExt == "cxx" or fileExt == "CXX" or fileExt == "xx" or fileExt == "XX": + resFile = self.Compile_xx_to_o(file, target, subHeritage) + listSubFileNeededToBuild.append(resFile) else: debug.verbose(" TODO : gcc " + self.originFolder + "/" + file) # generate end point: if self.type=='LIBRARY': - debug.info("(lib) " + self.name + ".a <== *.o"); + resFile = self.Link_to_a(listSubFileNeededToBuild, target, subHeritage) + self.localHeritage.AddSources(resFile) else: - debug.info("(bin) " + self.name + ".a <== *.o"); - #build ended ... - self.isBuild=True + resFile = self.Link_to_bin(listSubFileNeededToBuild, target, subHeritage) + # generate tree for this special binary + self.BuildTree(target, self.name) + + self.localHeritage.AddSub(subHeritage) + # return local dependency ... + return self.localHeritage + + # call here to build the module + def BuildTree(self, target, binaryName): + # ckeck if not previously build + if target.IsModuleBuildTree(self.name)==True: + return + #build tree of all submodules + for dep in self.depends: + inherit = BuildTree(dep, target, binaryName) + # add all the elements + self.files_to_staging(target, binaryName) + self.folders_to_staging(target, binaryName) + # call here to Clean the module - def Clean(self): + def Clean(self, target): for file in self.src: - debug.info(" " + self.name + " <- (X) " + file); + debug.error("TODO " + self.name + " <- (X) " + file); + + def CleanTree(self, target, binaryName): + for file in self.src: + debug.error("TODO " + self.name + " <- (X) " + file); + def AppendToInternalList(self, listout, list): if type(list) == type(str()): @@ -364,7 +477,8 @@ def AddModule(newModule): debug.error("try to insert a secont time the same module name : " + newModule.name) return moduleList.append(newModule) - buildList.AddModule(newModule.name) + # with "all" we just build the bianties and packages + buildList.AddModule(newModule.name, newModule.type) """ @@ -379,20 +493,26 @@ def Dump(): -def Build(name): +# return inherit packages ... +def Build(name,target): for module in moduleList: if module.name == name: - module.Build() - return - debug.error("request to build un-existant module name : '" + name + "'") + return module.Build(target) + debug.error("request to build an un-existant module name : '" + name + "'") - -def Clean(name): +def BuildTree(name,target,binName): for module in moduleList: if module.name == name: - module.Clean() + module.BuildTree(target,binName) return - debug.error("request to build un-existant module name : '" + name + "'") + debug.error("request to build tree on un-existant module name : '" + name + "'") + + +def Clean(name,target): + for module in moduleList: + if module.name == name: + module.Clean(target) + debug.error("request to clean an un-existant module name : '" + name + "'") diff --git a/corePython/target_Linux.py b/corePython/target_Linux.py index de90074..d1b7a5d 100755 --- a/corePython/target_Linux.py +++ b/corePython/target_Linux.py @@ -1,42 +1,109 @@ #!/usr/bin/python +import debug +import datetime +import buildTools +import environement - -TARGET_CC='gcc' -TARGET_CXX='g++' -TARGET_AR='ar' -TARGET_LD='ld' -TARGET_NM='nm' -TARGET_STRIP='strip' -TARGET_RANLIB='ranlib' -TARGET_DLLTOOL='dlltool' - - -############################################################################### -# Target global variables. -############################################################################### -TARGET_GLOBAL_C_INCLUDES='' -TARGET_GLOBAL_CFLAGS='' -TARGET_GLOBAL_CPPFLAGS='' -TARGET_GLOBAL_ARFLAGS='rcs' -TARGET_GLOBAL_LDFLAGS='' -TARGET_GLOBAL_LDFLAGS_SHARED='' -TARGET_GLOBAL_LDLIBS='' -TARGET_GLOBAL_LDLIBS_SHARED='' -TARGET_GLOBAL_CFLAGS_ARM='' -TARGET_GLOBAL_CFLAGS_THUMB='' - -TARGET_STATIC_LIB_SUFFIX='.a' -TARGET_EXE_SUFFIX='' -TARGET_SHARED_LIB_SUFFIX='.so' -TARGET_OUT_FOLDER_BINARY='/usr/bin' -TARGET_OUT_FOLDER_LIBRAIRY='/usr/lib' -TARGET_OUT_FOLDER_DATA='/usr/share/' -TARGET_OUT_FOLDER_DOC='/usr/share/doc' -TARGET_OUT_PREFIX_LIBRAIRY='' -# define the target OS type for the compilation system ... -TARGET_GLOBAL_CFLAGS=' -D__TARGET_OS__Linux' -# basic define of the build time : -TARGET_GLOBAL_CFLAGS += ' -DBUILD_TIME="\"lkjlkjlkjlkjlkj\""' +class Target: + def __init__(self): + self.name='Linux' + debug.info("create board target : "+self.name); + if 1==environement.GetClangMode(): + self.cc='clang' + self.xx='clang++' + else: + self.cc='gcc' + self.xx='g++' + self.ar='ar' + self.ld='ld' + self.nm='nm' + self.strip='strip' + self.ranlib='ranlib' + self.dlltool='dlltool' + ############################################################################### + # Target global variables. + ############################################################################### + self.global_include_cc='' + self.global_flags_cc=['-D__TARGET_OS__Linux', "-DBUILD_TIME=\"\\\""+str(datetime.datetime.now())+"\\\"\""] + self.global_flags_xx='' + self.global_flags_mm='' + self.global_flags_m='' + self.global_flags_ar='rcs' + self.global_flags_ld='' + self.global_flags_ld_shared='' + self.global_libs_ld='' + self.global_libs_ld_shared='' + + self.suffix_dependence='.o' + self.suffix_obj='.o' + self.suffix_lib_static='.a' + self.suffix_lib_dynamic='.so' + self.suffix_binary='' + self.suffix_package='.deb' + + self.folder_arch="/" + self.name + + if 1==environement.GetDebugMode(): + self.buildMode = "debug" + else: + self.buildMode = "release" + self.folder_out="/out" + self.folder_arch + "/" + self.buildMode + self.folder_final="/final" + self.folder_staging="/staging" + self.folder_build="/build" + self.folder_bin="/usr/bin" + self.folder_lib="/usr/lib" + self.folder_data="/usr/share" + self.folder_doc="/usr/share/doc" + self.buildDone=[] + self.buildTreeDone=[] + + """ + return a list of 3 elements : + 0 : sources files (can be a list) + 1 : destination file + 2 : dependence files module (*.d) + """ + def GenerateFile(self,moduleName,basePath,file,type): + list=[] + if (type=="bin"): + list.append(file) + list.append(buildTools.GetRunFolder() + self.folder_out + self.folder_staging + self.folder_bin + "/" + moduleName + self.suffix_binary) + list.append(buildTools.GetRunFolder() + self.folder_out + self.folder_build + "/" + moduleName + "/" + moduleName + self.suffix_dependence) + elif (type=="obj"): + list.append(basePath + "/" + file) + list.append(buildTools.GetRunFolder() + self.folder_out + self.folder_build + "/" + moduleName + "/" + file + self.suffix_obj) + list.append(buildTools.GetRunFolder() + self.folder_out + self.folder_build + "/" + moduleName + "/" + file + self.suffix_dependence) + elif (type=="lib-shared"): + list.append(file) + list.append(buildTools.GetRunFolder() + self.folder_out + self.folder_staging + self.folder_lib + "/" + moduleName + self.suffix_lib_dynamic) + list.append(buildTools.GetRunFolder() + self.folder_out + self.folder_build + "/" + moduleName + "/" + moduleName + self.suffix_dependence) + elif (type=="lib-static"): + list.append(file) + list.append(buildTools.GetRunFolder() + self.folder_out + self.folder_build + "/" + moduleName + "/" + moduleName + self.suffix_lib_static) + list.append(buildTools.GetRunFolder() + self.folder_out + self.folder_build + "/" + moduleName + "/" + moduleName + self.suffix_dependence) + else: + debug.error("unknow type : " + type) + return list + + def GetStagingFolder(self, moduleName): + return buildTools.GetRunFolder() + self.folder_out + self.folder_staging + self.folder_data + "/" + moduleName + + def IsModuleBuild(self,module): + for mod in self.buildDone: + if mod == module: + return True + self.buildDone.append(module) + return False + + def IsModuleBuildTree(self,module): + for mod in self.buildTreeDone: + if mod == module: + return True + self.buildTreeDone.append(module) + return False + + """ TARGET_GLOBAL_LDFLAGS = "-L$(TARGET_OUT_STAGING)/lib diff --git a/make.py b/make.py index 0a22304..4886f91 100755 --- a/make.py +++ b/make.py @@ -6,10 +6,16 @@ import inspect import fnmatch sys.path.append(os.path.dirname(__file__) + "/corePython/" ) import debug + +countArgToPreventVerboseError = len(sys.argv) # preparse the argument to get the erbose element for debug mode for argument in sys.argv: if argument == "verbose": debug.SetLevel(5) + countArgToPreventVerboseError -= 1 + elif argument == "color": + debug.EnableColor() + countArgToPreventVerboseError -= 1 # now import other standard module import module @@ -39,12 +45,14 @@ def HelpDisplay(): print " ex: " + sys.argv[0] + " all board=Android all board=Windows all help" exit(0) + + """ Run everything that is needed in the system """ def Start(): # parse all argument - if len(sys.argv)==1: + if countArgToPreventVerboseError==1: #by default we build all binary for the current board buildList.Build("all") else: @@ -60,6 +68,9 @@ def Start(): elif argument == "verbose": # nothing to do ... None + elif argument == "color": + # nothing to do ... + None else: buildList.Build(argument)