OCaml Change Path of Standard Library - cygwin

I have installed OCaml on Windows using the 64-bit graphical installer found here.
When I run ocamlc -config in the Windows command prompt, It tells me that the standard library is located here:
standard_library_default: C:/cygwin/home/appveyor/.opam/4.12.0+mingw64c/lib
standard_library: C:/cygwin/home/appveyor/.opam/4.12.0+mingw64c/lib/ocaml
However, the cygwin directory does not exist at all, and I believe the standard library is actually located in
C:\OCaml64\home\MyUser\.opam\4.12.0+mingw64c\lib\ocaml
Is there any way to change the path of the standard library?

You can't override the standard_library_default as it is stored in the binary, but you can use the OCAMLLIB environment variable to override the standard_library path.
But most likely you don't need to change it. You should either run your commands in a cygwin terminal and activate your opam using
eval $(opam env)
Or, if you want to use a windows terminal, like cmd.exe you can use the ocaml-env helper for that, e.g.,
:: run cmd.exe
ocaml-env exec -- cmd.exe
:: start utop from the 4.03.0-mingw64 switch
ocaml-env exec --switch=4.03.0-mingw64 -- utop.exe
:: run utop inside ConEmu / Notepad
ocaml-env-win --switch=4.04.0-msvc32 -- "C:\\Program Files\\ConEmu\\ConEmu.exe" -run utop.exe
ocaml-env-win -- "C:\\Program Files\\Notepad++\\notepad++.exe"

Related

How do you get a launcher for firefox?

I hope that I'm tagging/asking on the correct page. I'm Using Linux Mint 6.0, but it could be OS independent.
So the used command for installing Firefox was
nix-env -iA nixpkgs.firefox-esr
When I type which firefox, I get:
/home/foo/.nix-profile/bin/firefox
So Linux Mint comes with Chrome preinstalled, which has a launcher, e.g. also in the start menu. How do I get that for firefox as well? I didn't find a tool to create such a launcher in Mint and I actually think, that nix should do that for me.
EDIT: I also found this page which seemed helpful and advertised e.g. the KDE Kickoff, but I wasn't able to get that one to run.
I can only speak for Ubuntu launchers, but other distros will have launcher files that will have a similar setup
TLDR, add ~/.nix-profile/share to XDG_DATA_DIRS env variable on login. Add the following to ~/.profile after nix loading commands
export XDG_DATA_DIRS=$HOME/.nix-profile/share:$XDG_DATA_DIRS
Explanation:
Installed packages via nix will have an immutable path in nix/store. ~/.nix-profile/bin/firefox is the derivation your current nix environment is linked to (if you update the firefox package, it'll point to the new one)
This means you can create a launcher file for that executable. Lets see if the firefox-esr derivation comes with a desktop launcher or not:
$ nix-build '<nixpkgs>' -A firefox-esr
This will build the package and give you a derivation path. For my current channel it is /nix/store/3iipcmiykgr4p34fg3rkicdz1bw584gm-firefox-102.2.0esr
If I check inside it, there is a .desktop file which defines Ubuntu launchers:
$ ls /nix/store/3iipcmiykgr4p34fg3rkicdz1bw584gm-firefox-102.2.0esr/share/applications
firefox.desktop
These files will also be available under ~/.nix-profile/share/applications so you can simply add that to XDG_DATA_DIRS env variable before boot
If an application did not have one, you can manually make one and add it under ~/.local/share/applications, then set the executable path to the nix one
So SuperSandro2000 explained in the comments, that firefox from nix ships with a .desktop file already. This can be easily added to the start menu and lies in
/nix/store/...-firefox-XXX.X/share/applications/firefox.desktop
If there is no such file included, the most direct way could be (imho) to just create a simple bash script:
#!/bin/bash
./home/foo/.nix-profile/bin/firefox & #Run Firefox
echo Firefox was started with PID $!
In order to make it runnable, enter chmod +x your_skript_name.sh. Afterwards, ./firefox 2> /dev/null & can be used instead to run it silently in the background.
You can also consider the developer/command line options for firefox (Archive) or this blog article here.
Maybe /usr/bin/menulibre is also the right application, it allows you to create .desktop files. This app can also be found by right-clicking on the start "menu".

How to stop the Cygwin terminal from forgetting the environment when opening it in a non-home folder?

I got Ocaml for Windows which comes prepackaged with Cygwin. Since I wanted to be able to open mintty from the command line in the current directory, so I added it to PATH and then just running mintty does the trick. While this causes it to open in the current directory the problem is that when I run any of the Ocaml executables like opam I get an error.
Marko#Lain /cygdrive/e/Webdev/Ocaml/todolist
$ opam
bash: opam: command not found
When I run it using mintty - like the shortcut does, this in fact works.
Marko#Lain ~
$ cd "E:\Webdev\Ocaml\todolist"
Marko#Lain /cygdrive/e/Webdev/Ocaml/todolist
$ opam
usage: opam [--version]
[--help]
<command> [<args>]
The most commonly used opam commands are:
init Initialize opam state, or set init options.
list Display the list of available packages.
show Display information about specific packages.
install Install a list of packages.
remove Remove a list of packages.
update Update the list of available packages.
upgrade Upgrade the installed package to latest version.
config Display configuration options for packages.
repository Manage opam repositories.
switch Manage multiple installation prefixes.
pin Pin a given package to a specific version or source.
admin Tools for repository administrators
See 'opam help <command>' for more information on a specific command.
What do I have to do so that I get this behavior normally?
Also, since mintty runs a terminal in a standalone window, it would be better to run bash, but bash - does not work for me. After I get this to work, I'd like to add bash to my list of VS Code shells and for that I'd need to understand how to run it in an arbitrary directory from the command line while keeping its memory of the home environment.
This command mintty - start your shell as login one.
If you run a not-login shell, most of the configuration script are not read, and enviroment is taken from the father process, but of course your link fails as Windows can not provide a proper one.
If you want to be able to open a login shell from explorer the best way is to install chere package
$ chere -h
/usr/bin/chere version 1.4
Usage:
/usr/bin/chere -<iuxlrhv> [-lracnmpf12] [-t <term>] [-s <shell>]
[-d <display> ] [-o <options>] [-e <menutext>]
Adds the stated terminal/shell combination to the folder context menu
This allows you to right click a folder in Windows Explorer and open
a Cygwin shell in that folder.
Options:
i - Install
u - Uninstall
x - Freshen eXisting entries
l - List currently installed chere items
r - Read all chere registry entries to stdout
a - All users
c - Current user only
n - Be Nice and provide Control Panel uninstall option (Default)
m - Minimal, no Control Panel uninstall
p - Print regtool commands to stdout rather than running them
f - Force write (overwrite existing, ignore missing files)
1 - Start using registry one-liners. This doesn't work with ash,
tcsh or network shares.
2 - Start via bash script. Relies on windows to change directory,
and login scripts avoiding doing a cd /home/Marco
h - Help
v - Version
t <term> - Use terminal term. Supported terminals are:
cmd rxvt mintty xterm urxvt
s <shell> - Use the named shell. Supported shells are:
ash bash cmd dash fish mksh pdksh posh tcsh zsh passwd
d <display> - DISPLAY to use (xterm, urxvt). Defaults to :0.
Set to env to use the runtime environment variable.
o <options> - Add <options> to the terminal startup command.
If more than one option is specified, they should all be
contained within a single set of quotes.
e <menutext> - Use <menutext> as the context menu text.
See the man page for more detail.
You can than install your preferred or default shell on explorer right click menu as an additional item. It will open a login shell in the chosen directory.

Nodejs terminal script problematic cygwin paths of arguments - cannot make an universal script

I have an issue with using node.js as a script language in the Cygwin terminal. The script is used not only on Cygwin, but also on other platforms like OS X or GNU/Linux (no issue there).
Local or absolute path arguments to the script are passed as Cygwin paths (example: /cygdrive/c/Users/username/Dir/some-file.txt), but node requires Windows path (example: C:\Users\username\Dir\some-file.txt).
There is a tool cygpath that is used to translate between the two, but because of the multiplatform requirement, I cannot hardcode them. I would not like to make any bash wrappers so I can keep it a one file script.
For example this would work: ./script $(cygpath -w /tmp/file), but I cannot require the users of the script to put cygpath every time they want to use it.
Node is installed as the windows binary and is invoked with a shabang: #!/usr/bin/env node. which nodejs yields /cygdrive/c/Program Files/nodejs/node.
TL;DR: is there any sane and portable way to trigger automatic path translation in Cygwin for arguments of a nodejs script?

Error trying to `#require "ctypes.foreign";;` in utop on Windows (Cygwin)

I managed to install and run OCaml + OPAM + utop on Windows (in Cygwin) thanks to the awesome guide by Jonathan Protzenko. In utop, I especially want to be able to use ctypes + ctypes.foreign to quickly experiment and prototype accessing various WinAPI calls. Theoretically, I managed to install the ctypes packages successfully (opam install ... succeeds). Unfortunately, when I try to actually load them in utop, they fail miserably with a surprising error message:
utop # #require "ctypes.foreign";;
Error: Reference to undefined global `Ctypes_closure_properties'
Trying to do the same in rlwrap ocaml gives a somewhat longer error message:
# #require "ctypes.foreign";;
C:\OCaml\lib\unix.cma: loaded
C:\OCaml\lib\bigarray.cma: loaded
C:\OCaml\lib\str.cma: loaded
C:\cygwin64\home\Mateusz\.opam\system\lib\bytes: added to search path
C:\cygwin64\home\Mateusz\.opam\system\lib\ctypes: added to search path
C:\cygwin64\home\Mateusz\.opam\system\lib\ctypes\ctypes.cma: loaded
C:\cygwin64\home\Mateusz\.opam\system\lib\ctypes\ctypes-foreign-base.cma: loaded
Cannot load required shared library dllctypes-foreign-base_stubs.
Reason: dllctypes-foreign-base_stubs.dll: Cannot resolve ffi_type_pointer.
C:\cygwin64\home\Mateusz\.opam\system\lib\ctypes\ctypes-foreign-unthreaded.cma: loaded
Characters -1--1:
#require "ctypes.foreign";;
Error: Reference to undefined global `Ctypes_closure_properties'
Note: full transcript of the sessions is here — it contains output of a utop session in the cmd.exe terminal, and also of an additional rlwrap ocaml session in the Cygwin terminal.
I have absolutely no idea why that happens, or how I could further try to debug/pinpoint/diagnose the situation, so that I could try to find some workaround. (And by the way — I'm a total newbie to OCaml & OPAM, although I'm reasonably experienced in C/C++ and Linux generally.) What follows are some questions I have, that I imagine might hopefully help nudge the problem enough to push me through the roadblock:
Is there a way to tweak a git repo (i.e. ctypes) locally and pass it to OPAM instead of the original github one?
I've managed to google up some comment, which seems to mention that "a static version of libffi" might work, as hinted also in ctypes issue #198; but I'm a total newbie to OCaml, and unfortunately I have no faintest idea how I could apply this suggestion to utop?
How can I tell OPAM which libffi to use for ctypes? (specifically, to use "static libffi"?)
How can I check if the mingw64-x86_64-libffi Cygwin package I do have installed is statically linked, or dynamically? or if both variants are provided, then which one is used by ctypes? I found some answers on SO regarding how to detect if a libffi.a is linked with PIC (?) relocations [-fpic?], but they all seemed really hackish and none of the ones I tried seemed really to work, at least in my case.
Any at all help would be highly appreciated. I don't even know who to ask about this, given it's at a crossing of OCaml, OPAM, utop and Cygwin, all of those being huge and somewhat unrelated/orthogonal systems. I've tried posting the issue on ctypes repo, but all it got over a month's time was a "patches-welcome" label.
mingw64-x86_64-libffi ships with static and dynamic libraries, but the gnu linker will use the dynamic versions by default.
Patching the build of ctypes would be very fiddling (the build system of ctypes is rather complex, a mix of scripts and makefiles). So just try the following: delete the dynamic libraries (/usr/x86_64-w64-mingw32/sys-root/mingw/lib/libffi.dll.a and /usr/x86_64-w64-mingw32/sys-root/mingw/bin/libffi-6.dll), rebuild ctypes and then restore the deleted files.
opam-repository-mingw
By the way: https://fdopen.github.io/opam-repository-mingw/installation/ contains a patched version of flexdll (https://github.com/alainfrisch/flexdll/pull/3 applied - the problem is not specific to libffi) that supports the dynamic and static versions of libffi. opam install ctypes-foreign ctypes utop should work out of the box, if /usr/x86_64-w64-mingw32/sys-root/mingw/bin is in your PATH. Full step-by-step guide below:
Download a 64-bit graphical installer and run it.
After installation completes, start the "Cygwin64 Terminal" (gets installed into Cygwin group in the Start Menu).
Type cygwin-install gui to start the Cygwin Setup/Installer and use it to install some text editor (joe or nano or vim or whatever you prefer).
Use the text editor you installed to edit your ~/.bashrc file, add the following line:
export PATH="/usr/x86_64-w64-mingw32/sys-root/mingw/bin:$PATH"
then execute it in your Cygwin Terminal (just type it in the terminal, or run the following command instead):
$ source ~/.bashrc
Install depext which will auto-download any required OS level (native) dependencies for OPAM packages, the use it to install ctypes and utop:
$ opam install depext depext-cygwinports
$ opam depext -i ctypes-foreign ctypes utop
Switch from Cygwin Terminal to cmd.exe, for example by typing the following command in Cygwin Terminal:
$ cmd /c start cmd
Start utop in cmd.exe terminal, and use it to call the MessageBox WinAPI function as a test that all's working well:
c:> utop
utop # #require "ctypes.foreign";;
utop # let dll = Dl.dlopen ~filename:"user32.dll" ~flags:[];;
val dll : Dl.library = <abstr>
utop # open Ctypes;;
utop # let mb =
Foreign.foreign ~from:dll "MessageBoxA"
(ptr void #-> string #-> string #-> uint #-> returning int) ;;
val mb : unit Ctypes_static.ptr -> bytes -> bytes -> Unsigned.uint -> int =
<fun>
utop # mb null "hello" "world" Unsigned.UInt.zero;;
- : int = 1
utop # #quit;;
c:>
[NOTE: not all of the above utop commands may be required, but that's what worked for me.]

Can't use "." to execute files with cygwin

I recently installed Cygwin on Windows 8.1, it works great but I can't execute file using the dot, for example "./hello.ml". I'm using the Windows's command prompt.
When I try using it, it show me that "." is not reconized. How can I make it works ?
Thanks.
You need to use the cygwin terminal or powershell instead.
The command interpreter doesn't think that your files are executable because they aren't one of the types that are recognized as binary executables. In general, Windows would use file associations from the registry to make things happen when you try to run a file. The cygwin terminal follows the unix-like convention and knows that your scripts are ml files and they are executable by using the ml interpreter, most likely from a #! at the top of your file.

Resources