implementation module CpmLogic /** * Clean libraries imports */ import StdEnv,StdStrictLists from StdOverloadedList import ++|,Last,Init,RemoveAt,SplitAt,instance length [!!] import set_return_code,Directory /** * CPM imports */ import AbsSyn,CpmPaths /** * CleanIDE imports */ import UtilIO,IdeState,Platform,PmPath,PmEnvironment,PmProject,PmDriver from PmCleanSystem import :: CompileOrCheckSyntax(..) /** * Execute a general CPM action */ doCpmAction :: String String !CpmAction !*World -> *World doCpmAction cleanhome pwd CpmMake world = doMake cleanhome pwd world doCpmAction cleanhome pwd (Project pn pa) world = doProjectAction cleanhome pwd pn pa world doCpmAction cleanhome pwd (Module mn ma) world = doModuleAction cleanhome mn ma world doCpmAction cleanhome pwd (Environment ea) world = doEnvironmentAction cleanhome pwd ea world doCpmAction _ _ _ world = help "cpm " [ "Where is one of the following:" , " [--force] [--envs=filename] : build project ." , " Optionally force build (default: 'false')" , " Optionally specify the environments file (default: 'IDEEnvs')" , " project : project actions" , " module : module actions" //, " environment : environment actions" , " make : build all projects in the current directory" , "" , "Execute `cpm help` to get help for specific actions."] world /** * Find all project files in the current working directory and build them */ doMake :: String !String !*World -> *World doMake cleanhome pwd world # ((ok,pwd_path),world) = pd_StringToPath pwd world | not ok = error ("Failed to read current directory ("+++pwd+++")") world # ((err,entries), world) = getDirectoryContents pwd_path world | err<>NoDirError = error ("Failed to read current directory ("+++pwd+++")") world # xs = [e \\ {fileName=e}<-entries | size e>=4 && e.[size e-4]=='.' && e.[size e-3]=='p' && e.[size e-2]=='r' && e.[size e-1]=='j'] | isEmpty xs = error ("No project file found in " +++ pwd) world = foldr (\pn -> doProjectAction cleanhome pwd pn (BuildProject False EnvsFileName)) world xs /** * Default compiler options. Currently it is a simple alias for * forwards-compatibility. */ compilerOptions :: CompilerOptions compilerOptions = DefaultCompilerOptions getLine :: *World -> *(String, *World) getLine world # (console, world) = stdio world # (line, console) = freadline console # (_, world) = fclose console world = (line, world) /** * Execute project-specific actions */ doProjectAction :: String String String ProjectAction *World -> *World doProjectAction cleanhome pwd pn (CreateProject mtemplate) world //Check if main module exists # (exists,world) = accFiles (FExists mainmodule) world | not exists # world = showLines ["Main module " +++ mainmodule +++ " does not exist. Create it? [y/n]"] world # (line, world) = getLine world | line.[0] == 'y' = mkMainAndProject world | otherwise = error ("Failed to create project. Need " +++ mainmodule) world | otherwise = mkProject world where mainmodule = MakeImpPathname pn mkMainAndProject world # world = doModuleAction "" mainmodule (CreateModule ApplicationModule) world = mkProject world mkProject world # edit_options = {eo={newlines=NewlineConventionUnix},pos_size=NoWindowPosAndSize} # projectfile = GetLongPathName (MakeProjectPathname pn) = case mtemplate of Nothing # prj = PR_NewProject mainmodule edit_options compilerOptions DefCodeGenOptions DefApplicationOptions [!!] DefaultLinkOptions # prj = PR_SetRoot mainmodule edit_options compilerOptions prj = saveProject cleanhome pwd prj projectfile world (Just template_file_path) # template_file_path = GetLongPathName template_file_path # ((ok, prj, errmsg), world) = accFiles (read_project_template_file template_file_path cleanhome) world | not ok = error ("Couldn't open project template: " +++ errmsg) world # ((ok, prj), world) = accFiles (create_new_project_using_template (pwd+++DirSeparatorString+++mainmodule) projectfile compilerOptions edit_options prj) world | not ok = error "Couldn't convert project template to project file" world = saveProject cleanhome pwd prj projectfile world doProjectAction cleanhome pwd pn ShowProject world # (proj_path, project, ok, world) = openProject pwd pn cleanhome world | not ok = world = showLines [ "Content of " +++ proj_path +++ ":" , "ProjectRoot..: " +++ PR_GetRelativeRootDir project , "Target.......: " +++ PR_GetTarget project , "Executable...: " +++ PR_GetExecPath project , "Paths........:" : showPaths project ] world doProjectAction cleanhome pwd pn (BuildProject force ideenvs) world # (envs, world) = readIDEEnvs cleanhome ideenvs world # (proj_path, proj, ok, world) = openProject pwd pn cleanhome world | not ok = world //Sanity checks on the project file to see if it is tampered with # appopts = PR_GetApplicationOptions proj | appopts.stack_traces && not appopts.profiling = abort "Stack tracing is enabled but time profiling is not\n" # (console, world) = stdio world # iniGeneral = initGeneral True compilerOptions cleanhome proj_path proj envs console # {ls, gst_world} = pinit force {ls=iniGeneral,gst_world=world,gst_continue_or_stop=False} = gst_world where pinit force_rebuild gst = BringProjectUptoDate force_rebuild cleanup gst cleanup exepath bool1 bool2 ps = abortLog (not bool2) "" ps doProjectAction cleanhome pwd pn (Compile module_names) world # (envs, world) = readIDEEnvs cleanhome EnvsFileName world (project_path, project, ok, world) = openProject pwd pn cleanhome world | not ok = world # (console, world) = stdio world iniGeneral = initGeneral False compilerOptions cleanhome project_path project envs console gst = {ls=iniGeneral,gst_world=world,gst_continue_or_stop=False} gst = foldl (\gst module_name->CompileProjectModule Compilation module_name project (\_ _ _ gst->gst) gst) gst module_names = gst.gst_world doProjectAction cleanhome pwd pn (ProjectPath pa) world # (proj_path, project, ok, world) = openProject pwd pn cleanhome world | not ok = world = doProjectPathAction cleanhome pwd pn project pa world doProjectAction cleanhome pwd pn (SetRelativeRoot relroot) world = withProject pwd pn cleanhome (uncurry (change_root_directory_of_project relroot) o PR_GetRootPathName) world doProjectAction cleanhome pwd pn (SetTarget target) world = withProject pwd pn cleanhome (PR_SetTarget target) world doProjectAction cleanhome pwd pn (SetExec exec) world = withProject pwd pn cleanhome (PR_SetExecPath exec) world doProjectAction cleanhome pwd pn (SetBytecode Nothing) world = withProject pwd pn cleanhome (\p->PR_SetByteCodePath (bytecode_path (PR_GetExecPath p)) p) world where bytecode_path exec_path | exec_path % (size exec_path-4,size exec_path-1) == ".exe" = exec_path % (0,size exec_path-4) +++ "bc" = exec_path +++ ".bc" doProjectAction cleanhome pwd pn (SetBytecode (Just bcfile)) world = withProject pwd pn cleanhome (PR_SetByteCodePath bcfile) world doProjectAction cleanhome pwd pn (ExportTemplate prt) world # (project_path, project, ok, world) = openProject pwd pn cleanhome world | not ok = error "Error opening project" world # (ok, world) = accFiles (save_project_template_file prt project cleanhome) world | not ok = error "Error saving project template" world = world doProjectAction cleanhome pwd pn (SetProjectOptions project_options) world = withProject pwd pn cleanhome (set_project_options project_options) world where set_project_options [project_option:project_options] project # project = set_project_option project_option project = set_project_options project_options project set_project_options [] project = project set_project_option DynamicsOn project = PR_SetApplicationOptions {PR_GetApplicationOptions project & dynamics = True} project set_project_option DynamicsOff project = PR_SetApplicationOptions {PR_GetApplicationOptions project & dynamics = False} project set_project_option GenericFusionOn project = PR_SetApplicationOptions {PR_GetApplicationOptions project & generic_fusion = True} project set_project_option GenericFusionOff project = PR_SetApplicationOptions {PR_GetApplicationOptions project & generic_fusion = False} project set_project_option DescExLOn project = PR_SetApplicationOptions {PR_GetApplicationOptions project & desc_exl = True} project set_project_option DescExLOff project = PR_SetApplicationOptions {PR_GetApplicationOptions project & desc_exl = False} project set_project_option (HeapSize hs) project = PR_SetApplicationOptions {PR_GetApplicationOptions project & hs = hs} project set_project_option (StackSize ss) project = PR_SetApplicationOptions {PR_GetApplicationOptions project & ss = ss} project set_project_option (Output output) project = PR_SetApplicationOptions {PR_GetApplicationOptions project & o = output} project set_project_option RTSFlagsOff project = PR_SetApplicationOptions {PR_GetApplicationOptions project & disable_rts_flags=True} project set_project_option RTSFlagsOn project = PR_SetApplicationOptions {PR_GetApplicationOptions project & disable_rts_flags=False} project set_project_option TimeProfileOff project = PR_SetApplicationOptions {PR_GetApplicationOptions project & profiling=False, stack_traces=False} project set_project_option TimeProfileOn project = PR_SetApplicationOptions {PR_GetApplicationOptions project & profiling=True, stack_traces=False} project set_project_option StackTraceOff project = PR_SetApplicationOptions {PR_GetApplicationOptions project & profiling=False, stack_traces=False} project set_project_option StackTraceOn project = PR_SetApplicationOptions {PR_GetApplicationOptions project & profiling=True, stack_traces=True} project set_project_option MemoryProfileOff project = PR_SetApplicationOptions {PR_GetApplicationOptions project & memoryProfiling=False} project set_project_option MemoryProfileOn project = PR_SetApplicationOptions {PR_GetApplicationOptions project & memoryProfiling=True} project set_project_option LinkerGenerateSymbolsOn project = PR_SetLinkOptions project {PR_GetLinkOptions project & generate_symbol_table=True} set_project_option LinkerGenerateSymbolsOff project = PR_SetLinkOptions project {PR_GetLinkOptions project & generate_symbol_table=False} set_project_option (PO_OptimiseABC val) project = PR_SetCodeGenOptions {PR_GetCodeGenOptions project & optimise_abc=val} project set_project_option (PO_GenerateByteCode val) project = PR_SetCodeGenOptions {PR_GetCodeGenOptions project & generate_bytecode=val} project set_project_option (PO_StripByteCode val) project = PR_SetLinkOptions project {PR_GetLinkOptions project & strip_bytecode=val} set_project_option (PO_KeepByteCodeSymbols val) project = PR_SetLinkOptions project {PR_GetLinkOptions project & keep_bytecode_symbols=val} set_project_option (PO_PreLinkByteCode val) project = PR_SetLinkOptions project {PR_GetLinkOptions project & prelink_bytecode=val} doProjectAction _ _ _ _ world = help "cpm project " [ "Where is one of the following" , " create [] : create a new project from an optional template" , " compile [..] : compile the given modules" , " show : show project information" , " build [--force] [--envs=filename] : build the project. Optionally force build (default: 'false')" , " Optionally specify the environments file (default: 'IDEEnvs')" , " path : manage project paths" , " root .[.] : set the project root relative to the project file." , " : . is the same dir, .. the parent, ... the grandparent, etc." , " target : set target environment to " , " exec : set executable name to " , " bytecode [bc] : set bytecode file to or .bc if no file given" , " template : export the given project to a template file" , " set