How setup Visual Studio Code for Run/Debug of F# projects/scripts? - macos

I have tried to use Visual Studio Code for run a simple F# script.
I download all recent versions as today. I install all the plugins at http://ionide.io/. Despite the nice animated gifs that show that it works, I'm unable to see how make to work the Build of code.
I create a .ionide file:
[Fake]
linuxPrefix = "mono"
command = "build.cmd"
build = "build.fsx"
But then, how install Fake? So, I do this from xamarin and install it. Ok, so now I get the build.fsx:
#r "packages/FAKE.4.12.0/tools/FakeLib.dll" // include Fake lib
RestorePackages()
// Properties
let buildDir = "./build/"
let testDir = "./test/"
let deployDir = "./deploy/"
// version info
let version = "0.2" // or retrieve from CI server
// Targets
Target "Clean" (fun _ ->
CleanDirs [buildDir; testDir; deployDir]
)
Target "fakeBuild" (fun _ ->
!! "./*.fsproj"
|> MSBuildRelease buildDir "Build"
|> Log "AppBuild-Output: "
)
Target "Default" (fun _ ->
trace "Hello World from FAKE"
)
// Dependencies
"Clean"
==> "fakeBuild"
==> "Default"
// start build
RunTargetOrDefault "Default"
Run the Fake:Build command and get:
No handler found for the command: 'fake.fakeBuild'. Ensure there is an activation event defined, if you are an extension.
And now get lost.

install yeoman: ">ext install yeoman"
then setup a stand alone project with >yo
and follow the instructions and say yes to paket and FAKE.
then >paket init
and >paket install and it should work.
to get the > use ctrl+shift+p
For the Atom IDE you also have to install the yeoman npm package which I describe here: http://www.implementingeventsourcingwithfsharp.com/?p=61
how to install the package is descibed here: https://www.npmjs.com/package/generator-fsharp
not sure you need it for Visual Studio Code
Hope this helps

the usual way of doing this is to have a bash script that calls your F# script. Your bash script should look like something like:
#!/bin/bash
if test "$OS" = "Windows_NT"
then # For Windows
.paket/paket.bootstrapper.exe
exit_code=$?
if [ $exit_code -ne 0 ]; then
exit $exit_code
fi
.paket/paket.exe restore
exit_code=$?
if [ $exit_code -ne 0 ]; then
exit $exit_code
fi
packages/FAKE/tools/FAKE.exe $# --fsiargs build.fsx
else #For non Windows
mono .paket/paket.bootstrapper.exe
exit_code=$?
if [ $exit_code -ne 0 ]; then
exit $exit_code
fi
mono .paket/paket.exe restore
exit_code=$?
if [ $exit_code -ne 0 ]; then
exit $exit_code
fi
mono packages/FAKE/tools/FAKE.exe $# --fsiargs build.fsx
fi
Now, you can define your build steps in your build.fsx script
#r "packages/FAKE/tools/FakeLib.dll"
open Fake
// Targets
// Dependencies
// Default target
Hope it helps.

I got it working.
That said, I'm almost as lost as you, the available documentation is not very complete IMO. Here's what you have to do (you tagged osx-elcapitan so I'm assuming OS X):
get rid of the .ionide file, you only need it if you don't want to use the defaults. Lets stick to the defaults for now to keep things simple.
make sure the path to FakeLib.dll is correct in your build.fsx
Create a file named build.sh with the following script (make sure the path to FAKE.exe is right):
mono packages/FAKE.4.12.0/tools/FAKE.exe build.fsx $#
If it fails again, post the output error (click the OPEN button at the top for the FAKE command)
PS: Your question is two months old so I apologize if you know all this already.

Related

How do I exit immediately in conditional command? [duplicate]

I am making a presubmit script. It looks like this:
function presubmit() {
gradle test android
gradle test ios
gradle test server
git push origin master
}
I want the function to exit, if any of the tests fail so it won't push a bug to git. How?
1. Use subshell ( .. ) with set -e; to make it more concise, you can do this:
build() {( set -e # Fail early
build_cmd_step_1
build_cmd_step_2
build_cmd_step_3
...
)}
Then, the function will fail on the first failure and you can intercept the exit status:
build
exit_status=$?
if [ ${exit_status} -ne 0 ]; then
echo "We have error - build failed!"
exit "${exit_status}"
fi
2. Alternatively, the && \ chaining inside a function is also good (https://stackoverflow.com/a/51913013/1375784), though it might get bad if you have a bigger function.
Both methods can be good, depending on your use case (in some cases using subshells may cause some unwanted side effects)
The way I do it is to add && \ after every command in the function (except the last one).
function presubmit() {
gradle test android && \
gradle test ios && \
gradle test server && \
git push origin master
}
I would make script more granular:
#!/bin/bash
function test() {
gradle test android
gradle test ios
gradle test server
}
function push() {
git push origin master
}
# this subshell runs similar to try/catch
(
# this flag will make to exit from current subshell on any error inside test or push
set -e
test
push
)
# you catch errors with this if
if [ $? -ne 0 ]; then
echo "We have error"
exit $?
fi
We track error only inside test and push. You can add more actions outside of subshell where test and push run. You can also this way add different scope for errors (let consider it as try/catch)
You can do this:
# declare a wrapper function for gradle
gradle() {
command gradle "$#" || exit 1
}
presubmit() {
gradle test android
gradle test ios
gradle test server
git push origin master
}
declare -xf presubmit gradle
Call the function in a subshell as:
( presubmit )
Usually when I call a function and want an error message incase it fails I do this:
presubmit || { echo 'presubmit failed' ; exit 1; }
By adding the || flag, it will determine whether which expression is TRUE.
Hope this helps :)
Also others have given ways that map one to one to your case, I think a more generic view is better. Also using the || and && for such is a cryptic way of writing scripts (read: prone to ending up with bugs).
I think the following is much easier to work with long term:
function presubmit() {
if ! gradle test android
then
return 1
fi
if ! gradle test ios
then
return 1
fi
if ! gradle test server
then
return 1
fi
git push origin master
}
The return from the last command is returned by the function so we do not need to have an if/then there.
In your specific case, to avoid the duplication, you could use a for loop like so:
function presubmit() {
for name in android ios server
do
if ! gradle test ${name}
then
return 1
fi
done
git push origin master
}
Now, you may instead want to look at a pre-push hook which would probably be much better since whether you run your script or not, the push won't happen unless the hook succeeds.

equivalent of -e within a bash function [duplicate]

I am making a presubmit script. It looks like this:
function presubmit() {
gradle test android
gradle test ios
gradle test server
git push origin master
}
I want the function to exit, if any of the tests fail so it won't push a bug to git. How?
1. Use subshell ( .. ) with set -e; to make it more concise, you can do this:
build() {( set -e # Fail early
build_cmd_step_1
build_cmd_step_2
build_cmd_step_3
...
)}
Then, the function will fail on the first failure and you can intercept the exit status:
build
exit_status=$?
if [ ${exit_status} -ne 0 ]; then
echo "We have error - build failed!"
exit "${exit_status}"
fi
2. Alternatively, the && \ chaining inside a function is also good (https://stackoverflow.com/a/51913013/1375784), though it might get bad if you have a bigger function.
Both methods can be good, depending on your use case (in some cases using subshells may cause some unwanted side effects)
The way I do it is to add && \ after every command in the function (except the last one).
function presubmit() {
gradle test android && \
gradle test ios && \
gradle test server && \
git push origin master
}
I would make script more granular:
#!/bin/bash
function test() {
gradle test android
gradle test ios
gradle test server
}
function push() {
git push origin master
}
# this subshell runs similar to try/catch
(
# this flag will make to exit from current subshell on any error inside test or push
set -e
test
push
)
# you catch errors with this if
if [ $? -ne 0 ]; then
echo "We have error"
exit $?
fi
We track error only inside test and push. You can add more actions outside of subshell where test and push run. You can also this way add different scope for errors (let consider it as try/catch)
You can do this:
# declare a wrapper function for gradle
gradle() {
command gradle "$#" || exit 1
}
presubmit() {
gradle test android
gradle test ios
gradle test server
git push origin master
}
declare -xf presubmit gradle
Call the function in a subshell as:
( presubmit )
Usually when I call a function and want an error message incase it fails I do this:
presubmit || { echo 'presubmit failed' ; exit 1; }
By adding the || flag, it will determine whether which expression is TRUE.
Hope this helps :)
Also others have given ways that map one to one to your case, I think a more generic view is better. Also using the || and && for such is a cryptic way of writing scripts (read: prone to ending up with bugs).
I think the following is much easier to work with long term:
function presubmit() {
if ! gradle test android
then
return 1
fi
if ! gradle test ios
then
return 1
fi
if ! gradle test server
then
return 1
fi
git push origin master
}
The return from the last command is returned by the function so we do not need to have an if/then there.
In your specific case, to avoid the duplication, you could use a for loop like so:
function presubmit() {
for name in android ios server
do
if ! gradle test ${name}
then
return 1
fi
done
git push origin master
}
Now, you may instead want to look at a pre-push hook which would probably be much better since whether you run your script or not, the push won't happen unless the hook succeeds.

How to test a Makefile for missing dependencies?

Is there a way to test for missing dependencies that shows up when compiling a project with multiple jobs (-jN where N > 1)?
I often encounter packages, mostly open source, where the build process works fine as long as I use -j1, or -jN where N is a relatively low value such as 4 or 8 but if I used higher values likes 48, a little uncommon, it starts to fail due to missing dependencies.
I attempted to build myself a bash script that would, given a target, figure out all the dependencies and try to build explicitly each of those dependency with -j1 in order to validate that none are missing dependencies on their own. It appears to work with small / medium package but fails on more important one like uClibc for example.
I am sharing my script in here, as some people may understand better what I mean by reading code. I also hope that a more robust solution exists and could be shared back.
#!/bin/bash
TARGETS=$*
echo "TARGETS=$TARGETS"
for target in $TARGETS
do
MAKE="make"
RULE=`make -j1 -n -p | grep "^$target:"`
if [ -z "$RULE" ]; then
continue
fi
NEWTARGETS=${RULE#* }
if [ -z "$NEWTARGETS" ]; then
continue
fi
if [ "${NEWTARGETS}" = "${RULE}" ]; then
# leaf target, we do not want to test.
continue
fi
echo "RULE=$RULE"
# echo "NEWTARGETS=$NEWTARGETS"
$0 $NEWTARGETS
if [ $? -ne 0 ]; then
exit 1
fi
echo "Testing target $target"
make clean && make -j1 $target
if [ $? -ne 0 ]; then
echo "Make parallel will fail with target $target"
exit 1
fi
done
I'm not aware of any open source solution, but this is exactly the problem that ElectricAccelerator, a high-performance implementation of GNU make, was created to solve. It will execute the build in parallel and dynamically detect and correct for missing dependencies, so that the build output is the same as if it had been run serially. It can produce an annotated build log which includes details about the missing dependencies. For example, this simple makefile has an undeclared dependency between abc and def:
all: abc def
abc:
echo PASS > abc
def:
cat abc
Run this with emake instead of gmake and enable --emake-annodetail=history, and the resulting annotation file includes this:
<job id="Jf42015c0" thread="f4bfeb40" start="5" end="6" type="rule" name="def" file="Makefile" line="6" neededby="Jf42015f8">
<command line="7">
<argv>cat abc</argv>
<output>cat abc
</output>
<output src="prog">PASS
</output>
</command>
<depList>
<dep writejob="Jf4201588" file="/tmp/foo/abc"/>
</depList>
<timing invoked="0.356803" completed="0.362634" node="chester-1"/>
</job>
In particular the <depList> section shows that this job, Jf42015c0 (in other words, def), depends on job Jf4201588, because the latter modified the file /tmp/foo/abc.
You can give it a try for free with ElectricAccelerator Huddle.
(Disclaimer: I'm the architect of ElectricAccelerator)

Ebuild example for project in Go

I intend to create a Gentoo ebuild for a project written in Go, and I'm wondering whether this has been done before.
As building and installing a Go project from source seems sufficiently different compared to projects in other programming languages, it would be useful for me to compare to an existing ebuild for figuring out best practices.
However, in the current portage tree I can't find any package that would depend on "dev-lang/go". Is there such an ebuild, perhaps in an overlay?
How about go-overlay to look for example ebuilds? They wrote a special ebuild class for building Go apllications and libraries in a few lines. Let me use their dev-util/flint-0.0.4 ebuild as an illustration (all comments are mine):
EAPI=6
GOLANG_PKG_IMPORTPATH="github.com/pengwynn"
GOLANG_PKG_VERSION="c3a5d8d9a2e04296fba560d9a22f763cff68eb75"
# Many Go projects don't pin versions of their dependencies,
# so it may has to be done here. You might not need this step if
# the upstream already uses 'godep' or simular tool.
GOLANG_PKG_DEPENDENCIES=(
"github.com/codegangsta/cli:142e6cd241"
"github.com/fatih/color:1b35f289c4"
"github.com/octokit/go-octokit:4408b5393e"
"github.com/fhs/go-netrc:4422b68c9c"
"github.com/jingweno/go-sawyer:1999ae5763"
"github.com/shiena/ansicolor:264b056680"
"github.com/jtacoma/uritemplates:0a85813eca"
)
# Since many projects don't require custom build steps,
# this single line may be enough.
inherit golang-single
# Nothing special about these variables.
DESCRIPTION="Check your project for common sources of contributor friction"
HOMEPAGE="https://${GOLANG_PKG_IMPORTPATH}/${PN}"
LICENSE="MIT"
KEYWORDS="amd64 x86 arm"
# Prevent simulateneous installing with 'dev-go/flint'.
# Honestly, I was unable to this package on the Internet.
SLOT="0"
DEPEND="!dev-go/${PN}"
Here is a working example of an ebuild which installs a go project:
https://github.com/timboudreau/gentoo/blob/master/net-misc/syncthing/syncthing-0.11.7.ebuild
It is possible. I just made one in my overlay. It was a little bit painful, but it works.
There are a few important things, that have to be done.
Create golang eclasses in your repository, if you don't have go-overlay added in your system.
GOLANG_PKG_IMPORTPATH variable specifies a GitHub profile, from which will be downloaded source code.
GOLANG_PKG_DEPENDENCIES variable specifies GitHub repositories and particular commits of all dependencies.
inherit golang-single imports mentioned eclass and at the same time adds dev-lang/go into dependencies.
It looks like there's an existing, working ebuild.
From: https://gist.github.com/matsuu/233858 (and also found at http://git.overlays.gentoo.org/gitweb/?p=proj/glentoo-overlay.git;a=blob_plain;f=dev-lang/golang-platform/golang-platform-9999.ebuild;hb=HEAD)
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
EAPI="2"
inherit elisp-common eutils mercurial toolchain-funcs
DESCRIPTION="The Go Programming Language"
HOMEPAGE="http://golang.org/"
SRC_URI=""
EHG_REPO_URI="https://go.googlecode.com/hg/"
EHG_REVISION="release"
LICENSE="BSD"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE="emacs vim-syntax"
RESTRICT="test"
RDEPEND="sys-devel/gcc"
DEPEND="${RDEPEND}
emacs? ( virtual/emacs )
sys-devel/bison
sys-apps/ed"
S="${WORKDIR}/hg"
ENVFILE="${WORKDIR}/50${PN}"
src_prepare() {
GOBIN="${WORKDIR}/bin"
mkdir -p "${GOBIN}" || die
sed -i \
-e "/^GOBIN=/s:=.*:=${GOBIN}:" \
-e "/MAKEFLAGS=/s:=.*:=${MAKEOPTS}:" \
src/make.bash || die
sed -i \
-e "/^CFLAGS=/s:-O2:${CFLAGS}:" \
src/Make.conf || die
case ${ARCH} in
x86)
GOARCH="386"
;;
*)
GOARCH="${ARCH}"
;;
esac
case ${CHOST} in
*-darwin*)
GOOS="darwin"
;;
*)
GOOS="linux"
;;
esac
# *-nacl*)
# GOOS="nacl"
# ;;
cat > "${ENVFILE}" <<EOF
GOROOT="/usr/$(get_libdir)/${PN}"
GOARCH="${GOARCH}"
GOOS="${GOOS}"
EOF
. "${ENVFILE}"
export GOBIN GOROOT GOARCH GOOS
}
src_compile() {
cd src
PATH="${GOBIN}:${PATH}" GOROOT="${S}" CC="$(tc-getCC)" ./make.bash || die
if use emacs ; then
elisp-compile "${S}"/misc/emacs/*.el || die
fi
}
src_test() {
cd src
PATH="${GOBIN}:${PATH}" GOROOT="${S}" CC="$(tc-getCC)" ./run.bash || die
}
src_install() {
dobin "${GOBIN}"/* || die
insinto "${GOROOT}"
doins -r pkg || die
if use emacs ; then
elisp-install ${PN} "${S}"/misc/emacs/*.el* || die "elisp-install failed"
fi
if use vim-syntax ; then
insinto /usr/share/vim/vimfiles/plugin
doins "${S}"/misc/vim/go.vim || die
fi
doenvd "${ENVFILE}" || die
dodoc AUTHORS CONTRIBUTORS README || die
dohtml -r doc/* || die
}
pkg_postinst() {
elog "please don't forget to source /etc/profile"
}
Sorry, I haven't tested it as I don't have a running Gentoo instance right now. Hope it works.

How to force F# interactive to reference Gtk# by default?

I am mostly playing with F# on Linux and would like to get all the necessary GUI libraries (Gtk, Gdk, Atk, Glib, Pango, Cairo) to be referenced by default so that I can simply use:
open Gtk;;
without any additional typing.
My best guess would modifying the fsi launching script, which at the moment looks like that:
#!/bin/sh
exec /usr/bin/mono /usr/local/src/fsharp/bin/fsi.exe $#
Update: working version of the script as in Stephen's suggestion:
#!/bin/sh
exec /usr/bin/mono /usr/local/src/fsharp/bin/fsi.exe -r "/usr/lib/cli/atk-sharp-2.0/atk-sharp.dll" -r "/usr/lib/cli/glib-sharp-2.0/glib-sharp.dll" -r "/usr/lib/cli/gdk-sharp-2.0/gdk-sharp.dll" -r "/usr/lib/cli/gtk-sharp-2.0/gtk-sharp.dll" -r "/usr/lib/cli/pango-sharp-2.0/pango-sharp.dll" -r "/usr/lib/mono/2.0/Mono.Cairo.dll" $#
I wrote a little script that allows you to use Gtk# from F# Interactive (see below). It references the necessary Gtk# assemblies (you may need to modify the paths) and it also configures F# Interactive event loop, so that you can create and display widgets (such as Window) interactively.
If you want to get the support automatically, you'll need to run fsi.exe with a parameter to load the script on start mono /.../fsi.exe --load:load-gtk.fsx (assuming that you save the script as load-gtk.fsx)
[<AutoOpen>]
module GtkSharp
// Load some common Gtk# assemblies (from /usr/lib/mono/2.0/../gtk-sharp-2.0)
#r "../gtk-sharp-2.0/gtk-sharp.dll"
#r "../gtk-sharp-2.0/gdk-sharp.dll"
#r "../gtk-sharp-2.0/glib-sharp.dll"
#r "../gtk-sharp-2.0/atk-sharp.dll"
open Gtk
Application.Init()
fsi.EventLoop <-
{ new Microsoft.FSharp.Compiler.Interactive.IEventLoop with
member x.Run() = Application.Run() |> ignore; false
member x.Invoke f =
let res = ref None
let evt = new System.Threading.AutoResetEvent(false)
Application.Invoke(new System.EventHandler(fun _ _ ->
res := Some(f())
evt.Set() |> ignore ))
evt.WaitOne() |> ignore
res.Value.Value
member x.ScheduleRestart() = () }
It may be a little different in Linux, but in Windows you can reference assemblies on fsi startup by using -r. e.g.
#!/bin/sh
exec /usr/bin/mono /usr/local/src/fsharp/bin/fsi.exe -r /usr/somedll.dll $#
I am guessing add
-r:/path/to/gtk
or
--load:someStartupScript.fs
which maybe includes some #rs or whatnot. fsi /? and you'll figure it out.

Resources