{"id":17988068,"url":"https://github.com/lujun9972/elake","last_synced_at":"2026-01-18T22:01:38.957Z","repository":{"id":91558510,"uuid":"39294255","full_name":"lujun9972/elake","owner":"lujun9972","description":"elisp make","archived":false,"fork":false,"pushed_at":"2015-10-06T00:20:57.000Z","size":188,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-04T03:26:49.662Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lujun9972.png","metadata":{"files":{"readme":"Readme.org","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-18T10:06:31.000Z","updated_at":"2015-07-18T10:07:38.000Z","dependencies_parsed_at":"2023-03-05T11:56:01.554Z","dependency_job_id":null,"html_url":"https://github.com/lujun9972/elake","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lujun9972/elake","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lujun9972%2Felake","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lujun9972%2Felake/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lujun9972%2Felake/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lujun9972%2Felake/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lujun9972","download_url":"https://codeload.github.com/lujun9972/elake/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lujun9972%2Felake/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28552119,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T20:59:07.572Z","status":"ssl_error","status_checked_at":"2026-01-18T20:59:02.799Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-29T19:10:32.915Z","updated_at":"2026-01-18T22:01:38.942Z","avatar_url":"https://github.com/lujun9972.png","language":"Emacs Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+TITLE: Readme\n#+AUTHOR: DarkSun\n#+CATEGORY: elake\n#+DATE: [2015-07-10 周五 16:58]\n#+OPTIONS: ^:{}\n\n* elake简介\n仿真rake的elisp实现\n\n* 使用方法\n类似make,elake中的任务也分为两种,phony任务与file任务. 其中file任务对应操作系统中的一个文件路径.\n\n一个任务的依赖任务是否执行由以下表格表示:\n| 目标任务类型 | 依赖任务类型 | 依赖任务执行条件                     |\n|--------------+--------------+----------------------------------------------|\n| phony任务 | phony任务  | 依赖任务未执行                        |\n| file任务 | phony任务  | 依赖任务未执行                        |\n| phony任务  | file任务   | 依赖任务对应的文件不存在         |\n| file任务 | file任务 | 依赖任务对应的文件要比目标任务对应的文件更新 |\n\n** 定义任务\n定义任务的方法是使用宏 =(elake-task 目的任务 (依赖任务列表) 任务说明字符串 任务定义内容)=. \n\n例如我们这样定义一个做饭的过程:\n#+BEGIN_SRC emacs-lisp :tangle elakefile.el\n  (elake-task :purchaseVegetables nil\n        \"任务1 -- 买菜\"\n        (message  \"到沃尔玛去买菜。\"))\n\n  (elake-task :cook (:purchaseVegetables)\n      \"任务2 -- 做饭\"\n      (message  \"做一顿香喷喷的饭菜。\"))\n#+END_SRC\n\n上面代码定义了两个任务\n\n第一个任务的名称为\":purchaseVegetables\",它以\":\"开头,因此是一个phony任务.\n\n+ :purchaseVegetables任务的依赖任务列表为nil,表示它不依赖任何前置任务\n\n+ :purchaseVegetables任务的说明是\"任务1 -- 买菜\"\n\n+ :purchaseVegetables任务的内容是 =(message  \"到沃尔玛去买菜。\")=\n\n第二个任务的名称为\":cook\",它是一个phony任务. 它依赖于:purchaseVegetables任务.\n\n因此,在执行:cook任务前会先执行:purchaseVegetables\n#+BEGIN_EXAMPLE\n  $ elake :cook\n  到沃尔玛去买菜。\n  做一顿香喷喷的饭菜。\n#+END_EXAMPLE\n** 自动变量\n在任务定义中,可以使用$\u003c指代目标任务,使用$@指代依赖任务列表. 例如:\n#+BEGIN_SRC emacs-lisp :tangle elakefile.el\n  (elake-task :task1 (/etc/passwd)\n    \"测试自动变量\"\n    (message \"%s依赖于%s\" $\u003c $@))\n#+END_SRC\n\n执行任务:task1的结果为:\n#+BEGIN_EXAMPLE\n  $ elake :task1\n  :task1依赖于(/etc/passwd)\n#+END_EXAMPLE\n\n** 默认构建任务\nelake会将地一个定义的任务作为默认的构建任务. 当没有为elake指定构建哪个任务时,elake会构建默认的构建任务.\n\n例如,上面的例子中,我们地一个定义的任务是:purchaseVegetables任务,因此直接调用elake的结果为:\n#+BEGIN_EXAMPLE\n  $ elake\n  到沃尔玛去买菜。\n#+END_EXAMPLE\n\n** 命名空间\nelake支持命名空间的概念. 使用命名空间的格式为 =(elake-namespace 命名空间名称 其他elake命令...)=\n\n在命名空间内定义的phony任务,其完整的名称为\":命名空间名称:任务名称\",命名空间对file任务无效\n例如:\n#+BEGIN_SRC emacs-lisp :tangle elakefile.el\n  (elake-namespace home\n      (elake-task :write-blog (:turn-on-computer) ;注意,同一个命名空间内的依赖任务无需加命名空间前缀\n        \"写博客\"\n        (message  \"在家写博客\"))\n    (elake-task :turn-on-computer ()\n      \"打开电脑\"\n      (message  \"打开家里的电脑\")))\n#+END_SRC\n\n这里在home命名空间内定义了两个任务:\":home:write-bog和:home:turn-on-computer\".\n#+BEGIN_EXAMPLE\n  $ elake :home:write-blog\n  打开家里的电脑\n  在家写博客\n  $ elake :write-blog\n  未定义的任务::write-blog\n#+END_EXAMPLE\n\n目前支持命名空间的函数还有`elake-execute-task'和`elake-remove-task'\n** 给任务传递环境变量值\n给elake传递形如\"环境变量:=值\"的参数,可以设定环境变量的值\n#+BEGIN_SRC emacs-lisp  :tangle elakefile.el\n  (elake-task :set-env nil\n    \"设置环境变量\"\n    (message \"UNKNOW-ENV:%s\" (getenv \"UNKNOW-ENV\")))\n#+END_SRC\n\n若不传递环境变量,则有:\n#+BEGIN_EXAMPLE\n  $ elake :set-env\n  UNKNOW-ENV:nil\n#+END_EXAMPLE\n\n若传递环境变量,则:\n#+BEGIN_EXAMPLE\n  $ elake :set-env UNKNOW-ENV:=whatever\n  UNKNOW-ENV:whatever\n#+END_EXAMPLE\n\n** 给任务传递参数值\n可以在定义任务时,使用未定义的变量. 只需要通过形如\"变量=值\"的形式传递变量值就好. 例如\n#+BEGIN_SRC emacs-lisp  :tangle elakefile.el\n  (elake-task :say-hello-to  nil\n      \"给任务传递参数\"\n      (message \"hello to %s\" who))\n#+END_SRC\n\n若不传递参数值,则会执行出错\n#+BEGIN_EXAMPLE\n  $ elake :say-hello-to\n  Symbol's value as variable is void: who\n#+END_EXAMPLE\n\n若传递参数值,则\n#+BEGIN_EXAMPLE\n  $ elake  who=darksun :say-hello-to\n  hello to darksun\n#+END_EXAMPLE\n\n** 在任务中执行其他任务\n使用 =(elake-execute-task task)= 可以在任务内执行其他任务\n#+BEGIN_SRC emacs-lisp  :tangle elakefile.el\n  (elake-task :laundry nil\n    \"洗衣服\"\n    (message \"把所有衣服扔进洗衣机。\"))\n  (elake-task :today nil\n    \"今天的任务\"\n    (elake-execute-task :home:write-blog)\n    (elake-execute-task :laundry))\n#+END_SRC\n\n则调用:today任务,会以此执行:home:write-blog和:laundry任务\n#+BEGIN_EXAMPLE\n  $ elake :today\n  打开家里的电脑\n  在家写博客\n  把所有衣服扔进洗衣机。\n#+END_EXAMPLE\n\n** 在任务中删除其他任务\n使用 =(elake-remove-task task)= 可以删除其他任务.例如\n#+BEGIN_SRC emacs-lisp  :tangle elakefile.el\n  (elake-task :task-to-be-removed nil\n    \"待删除的任务\"\n    (message \"该任务会被:remove-task删除掉,删除掉后无法执行\"))\n  (elake-task :remove-task (:task-to-be-removed)\n    \"删除任务:task-to-be-removed\"\n    (elake-remove-task :task-to-be-removed)\n    (message \"%s被删除\" $@))\n\n  (elake-task :execute-removed-task (:remove-task)\n    \"删除任务测试\"\n    (elake-execute-task :task-to-be-removed))\n\n#+END_SRC\n\n在执行:remove-task前,可以执行:task-to-be-removed\n#+BEGIN_EXAMPLE\n  $ elake :remove-task\n  该任务会被:remove-task删除掉,删除掉后无法执行\n  (:task-to-be-removed)被删除\n#+END_EXAMPLE\n\n但执行:remove-task后,无法再执行:task-to-be-removed了\n#+BEGIN_EXAMPLE\n  $ elake :execute-removed-task\n  该任务会被:remove-task删除掉,删除掉后无法执行\n  (:task-to-be-removed)被删除\n  未定义的任务::task-to-be-removed\n#+END_EXAMPLE\n\n** 使用规则自动生成任务\n使用 =(elake-rule 目标任务的匹配正则表达式 依赖任务的替代表达式列表 任务内容)= 来定义规则,当执行未定义的任务时,elake会尝试使用规则生成该任务.\n\n这里匹配正则表达式必须为字符串,替代表达式列表为字符串或字符串列表. \n\n关于匹配正则表达式和替代表达式的说明请参见`replace-regexp'函数中的`REGEXP'和`TO-STRING'说明.\n\n例如:\n#+BEGIN_SRC emacs-lisp  :tangle elakefile.el\n  (elake-rule \":make-\\\\(.+\\\\)\" (\"\\\\1\")\n    \"测试rule\"\n    (message (shell-command-to-string (format \"ls -l %s\" (car $@)))))\n\n  (elake-rule \"[^:].*\" nil\n    \"测试rule\"\n    (message \"touch %s\" $\u003c)\n    (message (shell-command-to-string (format \"touch %s\" $\u003c))))\n#+END_SRC\n\n可以使用:make-xxx任务来显示xxx文件的内容,且若xxx文件不存在则创建该文件\n#+BEGIN_EXAMPLE\n  $ ls -l rule\n  rule: No such file or directory\n  $ elake :make-rule\n  touch rule\n\n  -rw-rw-r-- 1 lujun9972 lujun9972 0  7月 19 11:53 rule\n\n  $ elake :make-rule\n  -rw-rw-r-- 1 lujun9972 lujun9972 0  7月 19 11:53 rule\n\n#+END_EXAMPLE\n\n** 依赖任务列表中支持使用S-Form自动生成依赖任务\n依赖任务列表中支持使用S-Form自动生产依赖任务,若依赖任务为list,则该list会被作为S-Form来执行,该S-Form的执行结果应该为一个包含一个多个多个依赖任务的list.\n\n例如:\n#+BEGIN_SRC emacs-lisp  :tangle elakefile.el\n  (elake-task :blog (index.html (let (files)\n                                  (dotimes (num 3 files)\n                                    (push (format \"file-%s.html\" num) files))))\n    \"测试使用S-Form自动生成依赖任务\"\n    (message \"%s的依赖任务为%s\" $\u003c $@))\n#+END_SRC\n\n表示:blog的依赖任务为index.html,file-2.html,file-1.html,file-0.html\n\n因此:\n#+BEGIN_EXAMPLE\n  ~/elake $ elake :blog\n  touch index.html\n\n  touch file-2.html\n\n  touch file-1.html\n\n  touch file-0.html\n\n  :blog的依赖任务为(index.html file-2.html file-1.html file-0.html)\n#+END_EXAMPLE\n** 其他参数说明\n+ -f 配置文件路径 :: 使用指定的文件作为加载的配置文件. 默认使用`elakefile'或`elakefile.el'或`elakefile.elc'\n+ --task 任务... :: 显示任务说明,若省略后面的任务,则显示所有任务说明\n+ -p 任务... :: 显示任务的依赖任务,若省略后面的任务,则显示所有的任务依赖\n+ -h :: 显示帮助信息\n* 待完成事项\n+ [X] 增加file类型的任务\n+ [X] 增加命名空间的支持\n+ [X] 仿照make添加一些自动变量\n+ [X] 仿照make将第一个定义的任务作为默认的构建任务\n+ [ ] 如何支持emacs本身已经占有的那些option呢?\n+ [ ] 如何区分传递符号和字符串給emacs --script呢?\n+ [ ] 支持定义任务和定义依赖相分离\n+ [ ] 支持分多次添加依赖关系,这样就能用程序自动添加依赖关系\n+ [X] 支持模式规则来自动生成某类文件\n+ [X] 支持使用-f指定依赖文件,默认为elakefile或elakefile.el或elakefile.elc\n+ [X] 支持带参数的任务\n+ [X] 支持命令行设置环境参数\n+ [X] 提供删除已定义任务的机制\n+ [X] 依赖任务列表中支持使用S-Form自动生成依赖任务\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flujun9972%2Felake","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flujun9972%2Felake","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flujun9972%2Felake/lists"}