Development Environment Setup

CS-364: Programming Languages

Spring 2022

General Notes

  • Windows is generally poorly supported. There are instructions below for a native installation, but your instructor has only had marginal success installing everything. You are much better off setting this up using WSL or using a Raspberry Pi. We will provide support for a WSL installation, but are unlikely able to solve any native installation issues.
  • You are encouraged to commit your code to a private GitHub repository. Note that this repo must be private. Keeping a public repo with code from this course is an honor code violation. You can decide if you would like to split your code between multiple repositories (recommended) or keep everything in one repository. If you split up your code, you will need to follow the instructions below for each project.

MacOS

  • Download and install the LTS version of NodeJS
  • Open the Terminal application (in Applications/Utilities directory)
  • Run the following command:
                      
                        sudo npm install -g esy
                      
                    
    This installs the command-line tool, esy, that can manage a Reason project.
  • Make a new directory (folder) where you will keep all of your Reason code for the semester.
  • Skip to Visual Studio Code Setup

Windows (supported)

We will be using the Windows Subsystem for Linux to use Reason in this course. In general, Unix-based systems work better with this programming environment. There is a native installation below, but it is not supported.

  • Install the Windows Subsystem for Linux following these steps
    • I recommend the default Ubuntu distribution (just use the basic command)
    • If your computer doesn't support WSL2, I found WSL1 to work just fine.
  • Reboot your computer
  • Open the Ubuntu application that was installed. Follow the steps to create a user account for the linux subsystem.
  • You will use the Ubuntu terminal to interface with the linux subsystem.
  • Skip to Linux (Raspberry Pi) setup
  • Note: If you'd like to find the project folder you make in Linux from Windows, open a File Explorer window and navigate to \\wsl$, and open the mount point for ubuntu. In here, there should be a /home/<username> directory where you can find this folder you just made.

Windows Native (unsupported)

  • Download and install the LTS version of NodeJS
  • Open Command Prompt or PowerShell.
  • Run the following command:
                      
                        npm install -g esy
                      
                    
    This installs the command-line tool, esy, that can manage a Reason project.
  • Make a new directory (folder) where you will keep all of your Reason code for the semester.
  • Skip to Visual Studio Code Setup

Linux (Raspberry Pi)

  • In a terminal, execute each line individually. Note that Linux does not show what you type when it asks for a password.
                      
                        sudo apt update
                        sudo apt install -y build-essential curl git nano unzip
                        curl -fsSL https://deb.nodesource.com/setup_17.x | sudo -E bash -
                        sudo apt-get install -y nodejs
                        sudo npm install -g esy
                      
                    
    This installs the command-line tool, esy, that can manage a Reason project.
  • Next, run
                      
                        mkdir <name_for_your_project_folder_without_spaces>
                      
                    
    to make a directory (folder) where you will keep all of your Reason code for the semester.
  • Skip to Visual Studio Code Setup

Visual Studio Code Setup

  • Install Visual Studio Code. If you are using a Raspberry Pi, you can do this part on your own computer and connect VSCode to the Pi with SSH.
  • Launch Visual Studio Code
  • Platform-specific notes:
    • MacOS:
      • Type command + shift + p to bring up the command pallette. Start typing shell and sleection "Install 'code' command in PATH". This will let you launch a copy of VSCode opened to a specific directory.
    • Windows (WSL):
      • On the first launch, there will be a popup about WSL. Choose Install to add support for interacting with WSL.
      • In the lower-left corner, click the green block. From the dropdown, Select Remote-WSL: New Window. This will open a new window and install the necessary components to communicate with WSL.
    • Connecting Remotely to a Raspberry Pi:
      • Note the ip of the Pi
      • Click the "Extensions" menu on the left-hand pane (four boxes with on floating away).
      • In the extensions search pane, search for remote-ssh. Click Install.
      • In the lower-left corner, click the green block. From the dropdown, Select Remote-SSH: Connect to Host.
      • This will open a new window and prompt you for the address. Enter <username>@<ip> and press return.
      • Confirm the SHA256 fingerprint
      • The necessary software will be installed on your PI for remote development.
  • Choose File > Open Folder, and select the folder you created before.
  • Click the "Extensions" menu on the left-hand pane (four boxes with on floating away).
  • In the extensions search pane, search for ocaml-platform. Click Install.
  • We are now ready to set up our Reason project

Configure Reason Project

  • In VSCode, create a file name package.json. Add the following to this file and save it. This describes the software dependencies to the esy tool, which will download and install them.
                      
                        {
                          "esy": {
                            "build": "dune build -p cs-364"
                          },
                          "dependencies": {
                              "@opam/reason": "^3.7.0",
                              "@opam/dune": "2.9.1",
                              "ocaml": "4.12.0",
                              "@opam/sedlex": "2.5",
                              "@opam/yojson": "*"
                          },
                          "devDependencies": { 
                              "@opam/merlin": "*", 
                              "@opam/ocaml-lsp-server": "*",
                              "@opam/ocamlformat-rpc": "*",
                              "@opam/ocp-indent": "*",
                              "@opam/rtop": "^3.7.0"
                          },
                          "resolutions": {
                              "@opam/ocp-indent": "kevinaangstadt/ocp-indent:ocp-indent.opam#60ed167"
                          }
                        }
                      
                    
  • Create an empty file name cs-364.opam. This is used by Visual Studio Code to detect your Reason "sandbox" (the software we are about to install).
  • Create a file named .gitignore and paste the following contents in it. If you save this project with git, it will ignore certain files that are generated by the compiler.
                      
                        .DS_Store
                        /node_modules*
                        finalOutput/*.js
                        .merlin
                        .install
                        /lib/bs/
                        /lib/js/
                        /lib/ocaml/
                        *.log
                        .bsb.lock
                        /src/*.js
                        _esy
                        _build
                        *.install
                        *.bs.js
    
                        # Editor
                        /.idea/
                        /.vscode/
                      
                    
  • Create a folder named .vscode and create a file named settings.json inside of it. Add the follwoing to this file and save it. It tells VSCode to ignore some of the files generated by the esy tool. This can help a bit with compilation performance and stability.
                      
                        {
                          "files.exclude": {
                              "**/_esy": true,
                              "**/.esy": true
                          },
                          "files.watcherExclude": {
                              "**/_esy/**": true,
                              "**/.esy": true
                          },
                          "search.exclude": {
                              "**/_esy": true,
                              "**/.esy": true
                          }
                        }
                      
                    
  • Open the built-in terminal in VSCode. This will open to the directory of your project. You can open the terminal using the View > Terminal menu or typing ctrl + `.
  • Run the command esy. It should take a while to download, compile, and install software dependencies. You should not see any error messages if this worked.
  • You can test that everything is working by running esy x rtop. You should see a big prompt for Reason. You can exit this by typing ctrl + d. The output should be similar to the example below.
  •                 
                      esy
                      (out)info esy 0.6.12 (using package.json)
                      (out)info checking https://github.com/ocaml/opam-repository for updates...
                      (out)info checking https://github.com/esy-ocaml/esy-opam-override for updates...
                      (out)info resolving esy packages: done                         
                      (out)info solving esy constraints: done         
                      (out)info resolving npm packages: done
                      (out)info fetching: done                                                                    
                      (out)info installing: done                                                                             
                      (out)info building @opam/camomile@opam:1.0.2@42017332
                      (out)info building @opam/react@opam:1.2.1@0e11855f
                      (out)info building @opam/trie@opam:1.0.0@f4e510e2
                      (out)info building @opam/mmap@opam:1.1.0@a98cdc3b
                      (out)info building @opam/ocplib-endian@opam:1.2@008dc942
                      (out)info building @opam/trie@opam:1.0.0@f4e510e2: done
                      (out)info building @opam/mmap@opam:1.1.0@a98cdc3b: done
                      (out)info building @opam/mew@opam:0.1.0@65011d4b
                      (out)info building @opam/ocplib-endian@opam:1.2@008dc942: done
                      (out)info building @opam/lwt@opam:5.5.0@cd185346
                      (out)info building @opam/mew@opam:0.1.0@65011d4b: done
                      (out)info building @opam/react@opam:1.2.1@0e11855f: done
                      (out)info building @opam/mew_vi@opam:0.5.0@cf66c299
                      (out)info building @opam/mew_vi@opam:0.5.0@cf66c299: done
                      (out)info building @opam/lwt@opam:5.5.0@cd185346: done
                      (out)info building @opam/lwt_react@opam:1.1.5@9b9c268e
                      (out)info building @opam/lwt_log@opam:1.1.1@fc97477f
                      (out)info building @opam/lwt_react@opam:1.1.5@9b9c268e: done
                      (out)info building @opam/lwt_log@opam:1.1.1@fc97477f: done
                      (out)info building @opam/camomile@opam:1.0.2@42017332: done
                      (out)info building @opam/charInfo_width@opam:1.1.0@1a0889ea
                      (out)info building @opam/charInfo_width@opam:1.1.0@1a0889ea: done
                      (out)info building @opam/zed@opam:3.1.0@6e750e3e
                      (out)info building @opam/zed@opam:3.1.0@6e750e3e: done
                      (out)info building @opam/lambda-term@opam:3.1.0@552c7f90
                      (out)info building @opam/lambda-term@opam:3.1.0@552c7f90: done
                      (out)info building @opam/utop@opam:2.9.0@10af4ff3
                      (out)info building @opam/utop@opam:2.9.0@10af4ff3: done
                      (out)info building @opam/rtop@opam:3.7.0@79d8733d
                      (out)info building @opam/rtop@opam:3.7.0@79d8733d: done
    
    
                      esy x rtop
                      (out)──────────────────────────────┬─────────────────────────────────────────────────────────────┬──────────────────────────────
                      (out)                              │ Welcome to utop version 2.9.0 (using OCaml version 4.12.0)! │                              
                      (out)                              └─────────────────────────────────────────────────────────────┘                              
                      (out)
                      (out)                  ___  _______   ________  _  __
                      (out)                  / _ \/ __/ _ | / __/ __ \/ |/ /
                      (out)                / , _/ _// __ |_\ \/ /_/ /    /
                      (out)                /_/|_/___/_/ |_/___/\____/_/|_/
                      (out)
                      (out)  Execute statements/let bindings. Hit <​enter> after the semicolon. Ctrl-d to quit.
                      (out)
                      (out)        >   let myVar = "Hello Reason!";
                      (out)        >   let myList: list(string) = ["first", "second"];
                      (out)        >   #use "./src/myFile.re"; /* loads the file into here */
                      (out)
                      (out)Type #utop_help for help about using utop.
                      (out)
                      (out)Reason # 
                      (out)┌──────────────┬──────────────┬───────────────┬─────┬────┬───┬──────────┬─────┬───────────┬──────┬────────────┬───────┬───┐
                      (out)│Afl_instrument│Alias_analysis│Allocated_const│Annot│Arch│Arg│Arg_helper│Array│ArrayLabels│Asmgen│Asmlibrarian│Asmlink│Asm│
                      (out)└──────────────┴──────────────┴───────────────┴─────┴────┴───┴──────────┴─────┴───────────┴──────┴────────────┴───────┴───┘
                    
                  
  • Reload the VSCode window. You can do this by typing Type command + shift + p. Then, type reload and select the option that states Developer: Reload Window. When the window reloads, look down in the bottom left corner. You will likely see something that says esy(package.json). Click this and choose the option that has the same name as your project folder. This tells the Reason plugin in VSCode how to interface with your project.