├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── bin ├── dune └── mkocaml.ml ├── dune-project ├── lib ├── git │ ├── dune │ └── gitUtils.ml ├── io │ ├── dune │ └── ioUtils.ml ├── makefile │ ├── dune │ └── makefileUtils.ml └── opam │ ├── dune │ └── opamUtils.ml └── mkocaml.opam /.gitignore: -------------------------------------------------------------------------------- 1 | *.annot 2 | *.cmo 3 | *.cma 4 | *.cmi 5 | *.a 6 | *.o 7 | *.cmx 8 | *.cmxs 9 | *.cmxa 10 | 11 | # ocamlbuild working directory 12 | _build/ 13 | 14 | # ocamlbuild targets 15 | *.byte 16 | *.native 17 | 18 | # oasis generated files 19 | setup.data 20 | setup.log 21 | 22 | # Merlin configuring file for Vim and Emacs 23 | .merlin 24 | 25 | # Dune generated files 26 | *.install 27 | 28 | # Local OPAM switch 29 | _opam/ 30 | notes 31 | *DS_Store 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Chris Nevers 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: build 2 | 3 | build: 4 | @dune build @all 5 | @cp -f _build/default/bin/mkocaml.exe /usr/local/bin/mkocaml 6 | 7 | install: 8 | @dune install 9 | 10 | test: build 11 | @dune runtest 12 | 13 | doc: build 14 | @opam install odoc 15 | @dune build @doc 16 | 17 | clean: 18 | @dune clean 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🐪 Mkocaml 2 | 3 | A simple helper I use to generate OCaml projects. I constantly find myself struggling to remember `dune` commands for 4 | various tasks and how to setup opam files. This project is intended to solve that and make setup quicker. 5 | 6 | 7 | 8 | This tool generates: 9 | * Git repository 10 | * OCaml `.gitignore` 11 | * Executable or Library with `inline-tests` 12 | * Opam package 13 | * Copy of the executable to `/usr/local/bin` 14 | * Makefile with no nonsense commands 15 | 16 | # Install 17 | 18 | opam install mkocaml 19 | 20 | 21 | # Examples 22 | Creating a new executable 23 | 24 | > mkocaml -e new 25 | > make 26 | > new 27 | Hello, World! 28 | Creating a new library 29 | 30 | > mkocaml -l new 31 | > make 32 | 33 | ## Makefile 34 | 35 | |Makefile command|Description| 36 | |---|---| 37 | |`make` or `make build` | Builds the project with dune, copies exe to `/usr/local/bin` | 38 | |`make install` | Installs the dune projects| 39 | |`make test` | Runs unit tests| 40 | |`make clean` | Cleans the project with dune| 41 | |`make doc` | Generates the documentation for the project| 42 | | `make publish` | Publishes the opam package| 43 | 44 | ## Opam File 45 | 46 | `git config` is used to fill in details. 47 | 48 | The project will be versioned at `1.0` by default. For subsequent releases, update the version in this file and `Makefile` (under the `publish` section). 49 | 50 | Before publishing, ensure you fill in the `synopsis` section. 51 | 52 | # Contributions 53 | Contributions to `mkocaml` are greatly appreciated! ❤️ 54 | 55 | Please try to keep its implementation unassuming and configurable. 🙂 56 | -------------------------------------------------------------------------------- /bin/dune: -------------------------------------------------------------------------------- 1 | (executable 2 | (public_name mkocaml) 3 | (libraries unix ioUtils gitUtils makefileUtils opamUtils)) 4 | -------------------------------------------------------------------------------- /bin/mkocaml.ml: -------------------------------------------------------------------------------- 1 | open IoUtils 2 | open GitUtils 3 | open MakefileUtils 4 | open OpamUtils 5 | 6 | let lib_name = ref "" 7 | let exe_name = ref "" 8 | 9 | let bad_arg arg = 10 | raise @@ Arg.Bad (Format.sprintf "Unrecognized argument: %s" arg) 11 | 12 | let usage = 13 | Format.sprintf "Usage: %s [-l name] [-e name]" Sys.argv.(0) 14 | 15 | let specs = [ 16 | "-l", Arg.Set_string lib_name, ": Creates a library with the given name"; 17 | "-e", Arg.Set_string exe_name, ": Creates an executable with the given name"; 18 | ] 19 | 20 | let setup_exe project = 21 | Format.sprintf "dune init exec %s bin" project |> cmd_; 22 | begin 23 | if Sys.file_exists "Makefile" |> not then 24 | makefile project `Exec account |> write_file "Makefile" 25 | else 26 | update_makefile_for_exe project 27 | end; 28 | setup_opam project 29 | 30 | let setup_lib project = 31 | Format.sprintf "mkdir -p lib/%s/ && dune init lib %s lib/%s --inline-tests && touch lib/%s/%s.ml" 32 | project project project project project |> cmd_; 33 | if Sys.file_exists "Makefile" |> not then 34 | makefile project `Lib account |> write_file "Makefile"; 35 | setup_opam project 36 | 37 | let () = 38 | Arg.parse specs bad_arg usage; 39 | if String.length !lib_name > 0 then 40 | let _ = setup_git () in 41 | setup_lib !lib_name 42 | else 43 | if String.length !exe_name > 0 then 44 | let _ = setup_git () in 45 | setup_exe !exe_name 46 | else 47 | print_endline usage 48 | -------------------------------------------------------------------------------- /dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 1.11) 2 | (name mkocaml) 3 | -------------------------------------------------------------------------------- /lib/git/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name gitUtils) 3 | (libraries ioUtils)) 4 | -------------------------------------------------------------------------------- /lib/git/gitUtils.ml: -------------------------------------------------------------------------------- 1 | open IoUtils 2 | 3 | let username = exec "git config user.name" 4 | let email = exec "git config user.email" 5 | let dune_version = exec "dune --version" 6 | 7 | let account = 8 | let open String in 9 | username |> lowercase_ascii |> split_on_char ' ' |> concat "" 10 | 11 | let gitignore = 12 | " 13 | *.annot 14 | *.cmo 15 | *.cma 16 | *.cmi 17 | *.a 18 | *.o 19 | *.cmx 20 | *.cmxs 21 | *.cmxa 22 | 23 | # ocamlbuild working directory 24 | _build/ 25 | 26 | # ocamlbuild targets 27 | *.byte 28 | *.native 29 | 30 | # oasis generated files 31 | setup.data 32 | setup.log 33 | 34 | # Merlin configuring file for Vim and Emacs 35 | .merlin 36 | 37 | # Dune generated files 38 | *.install 39 | 40 | # Local OPAM switch 41 | _opam/ 42 | notes 43 | *DS_Store 44 | " 45 | 46 | let setup_git () = 47 | cmd_ "git init"; 48 | write_file ".gitignore" gitignore 49 | -------------------------------------------------------------------------------- /lib/io/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name ioUtils) 3 | (libraries unix)) 4 | -------------------------------------------------------------------------------- /lib/io/ioUtils.ml: -------------------------------------------------------------------------------- 1 | let exec cmd = cmd |> Unix.open_process_in |> input_line 2 | 3 | let cmd_ cmd = let _ = Sys.command cmd in () 4 | 5 | let write_file name str = 6 | let chan = open_out name in 7 | output_string chan str; 8 | close_out chan 9 | -------------------------------------------------------------------------------- /lib/makefile/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name makefileUtils) 3 | (libraries ioUtils)) 4 | -------------------------------------------------------------------------------- /lib/makefile/makefileUtils.ml: -------------------------------------------------------------------------------- 1 | let move_exe_to_bin project = function 2 | | `Exec -> Format.sprintf 3 | "\t@cp -f _build/default/bin/%s.exe /usr/local/bin/%s\n" project project 4 | | _ -> "" 5 | 6 | let update_makefile_for_exe project = 7 | Format.sprintf "sed -i \"\" 's#@dune build @all#@dune build @all\\\n\t@cp -f _build/default/bin/main.exe /usr/local/bin/%s\\\n#' Makefile" 8 | project |> IoUtils.cmd_ 9 | 10 | let makefile project project_type account = 11 | let mv_cmd = move_exe_to_bin project project_type in 12 | Format.sprintf 13 | "all: build 14 | 15 | build: 16 | \t@dune build @all 17 | %s 18 | install: 19 | \t@dune install 20 | 21 | test: build 22 | \t@dune runtest 23 | 24 | doc: build 25 | \t@opam install odoc 26 | \t@dune build @doc 27 | 28 | clean: 29 | \t@dune clean 30 | 31 | # Create a release on Github, then run git pull 32 | publish: 33 | \t@git tag 1.0 34 | \t@git push origin 1.0 35 | \t@git pull 36 | \t@opam pin . 37 | \t@opam publish https://github.com/%s/%s/archive/1.0.tar.gz 38 | " 39 | (* Move executables to /usr/local/bin *) 40 | mv_cmd 41 | (* Git account name *) 42 | account 43 | (* Git project name *) 44 | project 45 | -------------------------------------------------------------------------------- /lib/opam/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name opamUtils) 3 | (libraries ioUtils gitUtils)) 4 | -------------------------------------------------------------------------------- /lib/opam/opamUtils.ml: -------------------------------------------------------------------------------- 1 | open IoUtils 2 | open GitUtils 3 | 4 | let opam project = 5 | Format.sprintf 6 | " 7 | opam-version: \"2.0\" 8 | version: \"1.0\" 9 | authors: \"%s <%s>\" 10 | maintainer: \"%s <%s>\" 11 | homepage: \"https://github.com/%s/%s\" 12 | bug-reports: \"https://github.com/%s/%s/issues\" 13 | dev-repo: \"git://github.com/%s/%s.git\" 14 | synopsis: \"\" 15 | build: [ 16 | [\"dune\" \"subst\"] {dev} 17 | [\"dune\" \"build\" \"-p\" name \"-j\" jobs] 18 | ] 19 | 20 | depends: [ 21 | \"ocaml\" 22 | \"dune\" {>= \"%s\"} 23 | ] 24 | " 25 | (* Authors *) 26 | username email 27 | (* Maintainers *) 28 | username email 29 | (* Homepage *) 30 | account project 31 | (* Bug reports *) 32 | account project 33 | (* Dev repo *) 34 | account project 35 | (* Build depends on user's dune version *) 36 | dune_version 37 | 38 | let setup_opam project = 39 | let filename = project ^ ".opam" in 40 | if Sys.file_exists filename |> not then 41 | opam project |> write_file filename; cmd_ "dune build @install" 42 | -------------------------------------------------------------------------------- /mkocaml.opam: -------------------------------------------------------------------------------- 1 | 2 | opam-version: "2.0" 3 | version: "1.2" 4 | authors: "Chris Nevers " 5 | maintainer: "Chris Nevers " 6 | homepage: "https://github.com/chrisnevers/mkocaml" 7 | bug-reports: "https://github.com/chrisnevers/mkocaml/issues" 8 | dev-repo: "git://github.com/chrisnevers/mkocaml.git" 9 | synopsis: "Tool to generate OCaml projects" 10 | license: "BSD-3" 11 | build: [ 12 | ["dune" "subst"] {pinned} 13 | ["dune" "build" "-p" name "-j" jobs] 14 | ] 15 | 16 | depends: [ 17 | "ocaml" 18 | "dune" {>= "1.11.0"} 19 | "base-unix" 20 | ] 21 | --------------------------------------------------------------------------------