Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add helpful information to the SETUP.md #32

Closed
kytrinyx opened this issue Mar 16, 2015 · 50 comments
Closed

Add helpful information to the SETUP.md #32

kytrinyx opened this issue Mar 16, 2015 · 50 comments
Assignees

Comments

@kytrinyx
Copy link
Member

The contents of the SETUP.md file gets included in
the README.md that gets delivered when a user runs the exercism fetch
command from their terminal.

At the very minimum, it should contain a link to the relevant
language-specific documentation on
help.exercism.io.

It would also be useful to explain in a generic way how to run the tests.
Remember that this file will be included with all the problems, so it gets
confusing if we refer to specific problems or files.

Some languages have very particular needs in terms of the solution: nested
directories, specific files, etc. If this is the case here, then it would be
useful to explain what is expected.


Thanks, @tejasbubane for suggesting that we add this documentation everywhere.
See exercism.io#2198.

@jwood803 jwood803 self-assigned this Mar 23, 2015
@pminten
Copy link

pminten commented Jul 26, 2015

The SETUP.md file is rather unhelpful if you're an Linux command line user.

I've found the following to get me at least to the point where I can run the tests:

  • First in the xfsharp root dir run nuget Install nunit.runners -OutputDirectory packages -ExcludeVersion (only needed once)
  • Then in the exercise directory run something like fsharpc --target:library Bob.fs BobTest.fs -r ../packages/NUnit.Runners/tools/nunit.framework.dll to compile
  • Finally to test run MONO_PATH=../packages/NUnit.Runners/tools mono ../packages/NUnit.Runners/tools/nunit-console.exe BobTest.dll

This isn't perfect though since it doesn't let auto-complete work (needs fsproj files).

@pminten
Copy link

pminten commented Jul 26, 2015

Not sure how helpful it is, but with the following trimmed down Bob.fsproj I can get xbuild on Linux to build it with packages in xfsharp/packages. Unfortunately it doesn't solve the runner problem (I'm guessing that shouldn't be too hard, but I never used msbuild before).

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{116CC2F9-F987-4B3D-915A-34CAC04A73DA}</ProjectGuid>
    <OutputType>Library</OutputType>
    <RootNamespace>BobTest</RootNamespace>
    <AssemblyName>BobTest</AssemblyName>
    <Name>BobTest</Name>
    <BuildOrder>
      <BuildOrder>
        <String>BobTest.fs</String>
      </BuildOrder>
    </BuildOrder>
    <TargetFSharpCoreVersion>4.3.0.0</TargetFSharpCoreVersion>
    <MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
    <OutputPath>bin</OutputPath>
    <PlatformTarget>x86</PlatformTarget>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="mscorlib" />
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="FSharp.Core" />
    <Reference Include="nunit.framework">
      <HintPath>..\packages\NUnit.Runners\tools\nunit.framework.dll</HintPath>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Bob.fs" />
    <Compile Include="BobTest.fs" />
  </ItemGroup>
  <Choose>
    <When Condition="'$(VisualStudioVersion)' == '11.0'">
      <PropertyGroup>
        <FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
      </PropertyGroup>
    </When>
    <Otherwise>
      <PropertyGroup>
        <FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
      </PropertyGroup>
    </Otherwise>
  </Choose>
  <Import Project="$(FSharpTargetsPath)" Condition="Exists('$(FSharpTargetsPath)')" />
</Project>

@kytrinyx
Copy link
Member Author

/cc @jwood803 Just making sure you're seeing this.

@pminten
Copy link

pminten commented Jul 26, 2015

Improved version of .fsproj, this one runs unit tests after building:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Configuration>Debug</Configuration>
        <Platform>x86</Platform>
        <ProductVersion>8.0.30703</ProductVersion>
        <SchemaVersion>2.0</SchemaVersion>
        <ProjectGuid>{116CC2F9-F987-4B3D-915A-34CAC04A73DA}</ProjectGuid>
        <OutputType>Library</OutputType>
        <RootNamespace>BobTest</RootNamespace>
        <AssemblyName>BobTest</AssemblyName>
        <Name>BobTest</Name>
        <BuildOrder>
            <BuildOrder>
                <String>BobTest.fs</String>
            </BuildOrder>
        </BuildOrder>
        <TargetFSharpCoreVersion>4.3.0.0</TargetFSharpCoreVersion>
        <MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
        <OutputPath>bin</OutputPath>
        <PlatformTarget>x86</PlatformTarget>
        <MSBuildCommunityTasksPath>.</MSBuildCommunityTasksPath>
    </PropertyGroup>
    <ItemGroup>
        <Reference Include="mscorlib" />
        <Reference Include="System" />
        <Reference Include="System.Core" />
        <Reference Include="FSharp.Core" />
        <Reference Include="nunit.framework">
            <HintPath>..\packages\NUnit.Runners\tools\nunit.framework.dll</HintPath>
        </Reference>
    </ItemGroup>
    <ItemGroup>
        <Compile Include="Bob.fs" />
        <Compile Include="BobTest.fs" />
    </ItemGroup>
    <Choose>
        <When Condition="'$(VisualStudioVersion)' == '11.0'">
            <PropertyGroup>
                <FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
            </PropertyGroup>
        </When>
        <Otherwise>
            <PropertyGroup>
               <FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
            </PropertyGroup>
        </Otherwise>
    </Choose>
    <Target Name="NUnit">
        <PropertyGroup>
            <ExeLauncher Condition="('$(OS)' != 'Windows_NT')">mono</ExeLauncher>
        </PropertyGroup>
        <Exec Command="$(ExeLauncher) ..\packages\NUnit.Runners\tools\nunit-console.exe $(OutputPath)$(AssemblyName).dll"/>
    </Target>

    <Import Project="$(FSharpTargetsPath)" Condition="Exists('$(FSharpTargetsPath)')" />
    <Target Name="AfterBuild" DependsOnTargets="NUnit"></Target>
</Project>

@ErikSchierboom
Copy link
Member

@pminten @jwood803 @kytrinyx I am working on a command-line script that can build and test all exercises. Currently, it is intended to be used in the Travis build (#13), but I could probably rather easily amend it to allow it to run tests from the command-line. I could even do exercise-specific test runs. The only thing I'm not sure of: how can I supply additional files to users when they fetch the exercises?

@kytrinyx
Copy link
Member Author

kytrinyx commented Feb 2, 2016

Any files that you add to an exercise will be fetched to the user, unless it has [Ee]xample in the file name.

@ErikSchierboom
Copy link
Member

@kytrinyx To be clear, that means that if I add a file named "test.sh" in the folder exercise/atbash, that file will be downloaded when the atbash exercise is fetched?

Is it also possible to have a file fetched in the root of the language directory, in this case F#?

@kytrinyx
Copy link
Member Author

kytrinyx commented Feb 2, 2016

Correct -- adding a test.sh or even a bin/test.sh or whatever would be delivered to the user (subdirectories are included recursively).

Is it also possible to have a file fetched in the root of the language directory, in this case F#?

Not yet. It's on the wishlist, but I haven't had time to implement that. It would require changes to both the x-api and the cli.

@ErikSchierboom
Copy link
Member

Thanks for the heads-up. We'll wait for that then :)

@ErikSchierboom
Copy link
Member

@kytrinyx
Copy link
Member Author

kytrinyx commented May 4, 2016

No, it has totally gotten lost in the chaos, and I haven't worked on it. As of right now I am putting it on my "think about and make progress on this in the near future" list. Thanks for the reminder!

@ErikSchierboom
Copy link
Member

@kytrinyx No problem, I know you're terribly busy! Thanks for the heads-up.

@ErikSchierboom
Copy link
Member

@kytrinyx Slight bump :) Have you had the opportunity to think about the above issue (how to include extra files when fetching exercises)?

@kytrinyx
Copy link
Member Author

kytrinyx commented Aug 1, 2016

Oh, my. Not really. I am now in a new job and have finished 3 months of intense conference travel, so things are calming down a bit. We need this for several tracks, so I think it needs to go towards the top of the list (finally).

@ErikSchierboom
Copy link
Member

ErikSchierboom commented Aug 1, 2016

No problem! Great to hear its on the top of the list. Hurray! 🎉

@rebelwarrior
Copy link

Beyond the command line stuff (which is awesome) I've never been able to get a single test to successfully run on Xamarin Studio on a Mac.

@ErikSchierboom
Copy link
Member

@rebelwarrior Hmmm, that's odd. I'll see if I can find anything related to this.

@rebelwarrior
Copy link

I'm sure I'm doing something wrong. But the instructions aren't super clear for Mac.

On Aug 6, 2016, at 1:45 PM, Erik Schierboom notifications@github.com wrote:

@rebelwarrior Hmmm, that's odd. I'll see if I can find anything related to this.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@ErikSchierboom
Copy link
Member

I've been thinking on how to improve the workflow of the F# track, and I am considering creating an .fsproj file for each exercise. This project would already include the test file and a reference to NUnit. In theory, people could then fetch an exercise, open the fsproj file in their favorite editor and (if the editor supports it) compile and test it. I think for most people, this would be a very familiar workflow, which is obviously beneficial.

Another benefit would be that it opens up the possibility for creating a simple build script (using FAKE). That means that people would also be able to run their tests just by running a batch file. We could also provide this build script for every exercises.

The main "disadvantage" of the above suggestions is that there are more files fetched, and people might get a bit confused (although I think fsproj files will make sense for virtually everyone).

What do you think? @jwood803 @rebelwarrior @pminten @kytrinyx?

@rebelwarrior
Copy link

Sounds great to me. I think the ppl that are super familiar with VS will know what to do and ppl like me can rely on having the proper files downloaded.

Sent from my mobile.

On Aug 22, 2016, at 5:33 AM, Erik Schierboom notifications@github.com wrote:

I've been thinking on how to improve the workflow of the F# track, and I am considering creating an .fsproj file for each exercise. This project would already include the test file and a reference to NUnit. In theory, people could then fetch an exercise, open the fsproj file in their favorite editor and (if the editor supports it) compile and test it. I think for most people, this would be a very familiar workflow, which is obviously beneficial.

Another benefit would be that it opens up the possibility for creating a simple build script (using FAKE). That means that people would also be able to run their tests just by running a batch file. We could also provide this build script for every exercises.

The main "disadvantage" of the above suggestions is that there are more files fetched, and people might get a bit confused (although I think fsproj files will make sense for virtually everyone).

What do you think? @jwood803 @rebelwarrior @pminten @kytrinyx?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@jwood803
Copy link
Contributor

That would most likely be better for the users so they wouldn't have to go through the trouble of creating their own projects and would greatly simplify the documentation to get started with the track.

@kytrinyx
Copy link
Member Author

+100 for lowering the friction to getting started with the track.

@rmunn
Copy link
Contributor

rmunn commented Aug 30, 2016

I think that introducing people to FAKE and Paket, via a simple test.sh script that "automagically" does everything for you (à la build.sh from ProjectScaffold), is a great idea. One of the biggest hurdles for me when I was first starting out was finding a decent .fsproj to copy, because I sure wasn't going to write one by hand -- and being on Linux, I don't have easy access to Visual Studio at home. (I do at work, but at work I'm supposed to be working on our big C# project, not doing F# exercises). It would be great to have some simple documentation that says "To run your tests, do test.sh. This uses FAKE to build things, and Paket to download dependencies, and here are some links to read more about them if you want -- but the nice thing about them is that they Just Work, and you usually don't have to worry about them."

Then in later tests when you might want to introduce FParsec, or show how to use FsCheck for property-based testing, you can simply put a line in the README to say "For this exercise, first run paket add nuget FParsec, and then you'll be able to use the FParsec library. Now here are some hints on how to use it..."

@ErikSchierboom
Copy link
Member

Getting up to speed on FAKE and Paket was problematic for me when I started, so indeed the hope is that people will get to know it this way. Introducing FParsec later seems to be a great option, especially if we have people try to install it themselves.

@petertseng
Copy link
Member

petertseng commented Feb 17, 2017

  1. The exact script I used to test my F# submissions on Linux:
#!/bin/sh

set -e

if [ $# -eq 0 ]; then
  srcfile=$(ls -1 *.fs | grep -v Test)
  if [ -z "$srcfile" ]; then
    echo "found no .fs files, run in a directory with one, or specify one."
    echo "usage: $0 [srcfile [testfile]]"
    exit 1
  fi
fi

if [ $# -lt 2 ]; then
  testfile=*Test.fs
  testdll="$(echo $testfile | cut -d. -f1).dll"
else
  testfile=$2
  testdll="$(echo "$testfile" | cut -d. -f1).dll"
fi

srcdll="$(echo "$srcfile" | cut -d. -f1).dll"
nunit=/usr/lib/cli/nunit.framework-2.6.3/nunit.framework.dll

fsharpc -a $srcfile
fsharpc -a -r:$nunit -r $srcdll $testfile
nunit-console --noxml $testdll
rm $srcdll $testdll
  1. After Allow exercises to build and run on .NET Core #308 is complete, dotnet test will run the tests.

@stale
Copy link

stale bot commented Apr 29, 2017

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@rmunn
Copy link
Contributor

rmunn commented Apr 30, 2017

I think there's still value in keeping this one open, so this is a quick ping to prevent the issue being auto-closed. I'd still like to see some sort of scaffolding repo that a newbie could clone and have immediate access to FAKE, Packet, and a build.sh / build.cmd script.

@stale stale bot removed the wontfix label Apr 30, 2017
@kytrinyx kytrinyx added the pinned label May 5, 2017
@kytrinyx
Copy link
Member Author

kytrinyx commented May 5, 2017

I added the pinned label so probot wont close it for inactivity.

@Mousaka
Copy link
Contributor

Mousaka commented Aug 20, 2017

Any progress on this issue? I'm a Linux user and I'm totally lost how to get started.

@kytrinyx
Copy link
Member Author

@Mousaka I don't know that there has been any movement, but this would be a fantastic opportunity to figure out exactly what needs to go into there, if you're willing to help us think this through step by step.

The first thing I'm going to try to do is help narrow down where you're stuck—that might be an Exercism problem in general, or an F# problem specifically.

Have you ever used Exercism before? We're working on making Exercism easier to use and understand in general. We actually launched a prototype of a new design yesterday that's been in the works for quite a while. I wouldn't recommend trying the prototype yet if you're new to Exercism, but definitely check out the homepage as it does a great job of explaining what Exercism is: https://v2.exercism.io/

How new are you to F#? If you could say a little bit about what type of exposure you've had to F# before, that would help a lot.

And finally, I suppose, what have you done so far in the process of trying to get started on this track? (If it feels like the answer to that is "nothing, I have no idea where to begin" that's totally fine, too!)

@ErikSchierboom
Copy link
Member

@Mousaka At the moment, we don't have a detailed workflow. But you should be able to follow the instructions on http://fsharp.org/use/linux/

We will be porting the F# track over to .NET Core, which will make the whole track completely cross-platform.

@Mousaka
Copy link
Contributor

Mousaka commented Aug 20, 2017

@kytrinyx @ErikSchierboom Thanks for answering so quickly.
@kytrinyx I'll answer your questions and I can perhaps try to help out with this. I might try out the new beta of exercism later but I'm not sure if that is related to my current problem with fsharp?

Have you ever used Exercism before?

Yes, I have used it before and I've solved around 20 problems or so in Elm, Elixir, Java and JavaScript. My experience is that it has been fairly easy to get started - only being well familiar with Java and JavaScript before starting out.

How new are you to F#?

I am quite new to F# but I have read half a book about it and I have had a basic "hello world"-webserver-project working. After not coding for a while and having a new computer I decided to give F# a go again. This time i started out with the quite new "Rider" IDE from jetbrains. I managed to open an old project of the Exercism "Leap" problem - that I totally forgot how I set up - and I submitted a solution successfully. I can probably manage to do this again if I spend some more time but after one evening trying to do it with Rider unsuccessfully and with MonoDevelop AND with Visual Code (briefly) I really felt like giving up.

Edit:
After another 1½ hour spent today I managed to set up another exercism problem successfully but the setup is far from smooth compared to the other languages I've worked with in exercism.
What I did now is:

  1. fetch exercism problem
  2. Create new Library project, using Rider, with same name as the exercism test-file but without "test" at the end, e.g "SumOfMultiples", having checked the box "Put solution and project in the same directory" (this matters if you in the end want exercism CLI to find the file you want to submit). Here I tried for a long time to create a project with the same name as the exercism problem folder "sum-of-multiples" but that results in some kind of namespace problem that I was not able to solve.
  3. Move the exercism problem test file "SumOfMultiplesTest.fs" to my newly created project folder. (Took me a while before I realized this was an important step, earlier I just tried step 4 right away but then it would seem to work but the test file would not be able to open SumOfMultiples module)
  4. Right click on my project in Rider and clicked "Add existing item..." and selected the exercism test file that I had moved to project folder.
  5. Right click on my project again and this time clicked on "Manage Nuget packages" (This took me a surprisingly long time to find for some reason) and search for and install NUnit
  6. Remove the exercism problem folder "sum-of-multiples"
  7. Close project in Rider
  8. Rename my project folder from "SumOfMultiples" to "sum-of-multiples" and put in your exercism fsharp folder if it's not there already.
  9. Open project/solution (btw what is the difference in F#?)
  10. Code along and complete the problem, run tests etc.
  11. Submit solution.

I really don't want to do all these steps for every new problem. I'm sure of course there are a lot smarter ways to this than what I just did but they can probably be difficult for a newbie like me to find.

I hope this input can be of some help and I'm happy to try any suggested new solutions or help out more in some way.

Cheers

@kytrinyx
Copy link
Member Author

I might try out the new beta of exercism later but I'm not sure if that is related to my current problem with fsharp?

@Mousaka -- nope, it sounds like this is specifically linked to the F# track, since you've successfully used Exercism for other languages.

I really don't want to do all these steps for every new problem.

Ouch, yes! Neither would I.

@ErikSchierboom a few questions about this in general:

  • Is this the process that you use?
  • If not, is your process meaningfully different? Simpler?
  • Is the process pretty much the same no matter which editor/IDE one uses?
  • How much of this could be scripted?
  • Or, alternately—could we provide more boilerplate up front to simplify the process?

You mentioned switching to .NET Core to make the process cross-platform, would that still involve significant setup for each problem?

@robkeim
Copy link
Contributor

robkeim commented Aug 21, 2017

@Mousaka welcome to the F# track, and I'm sorry that you've had a rough time getting started :( I appreciate your tenacity and taking the time to share your feedback with us. I agree with @kytrinyx's assessment that this is an F# track issue not a larger, Exercism issue.

IMO, newcomers to a given track should be able to get the Hello World up and running quickly and seamlessly otherwise it's not going to entice people to stay with the track. With the current F# setup, particularly on Linux we have definitely not achieved that goal.

I'd like to breakdown my response into two parts:

  1. What (if anything) can we do in the short term to reduce the barrier of entry of the track?
  2. What is the long term vision for the track?

What (if anything) can we do in the short term to reduce the barrier of entry to the track?

For full disclaimer I am working on Windows so things aren't always the same, but when I did the F# track here was my flow:

Onetime setup:

  1. Create a FSharpExercisimSolutions fsproj** in a directory separate from the Exercism repo
  2. Install the Nunit NuGet package

Exercise per workflow:

  1. Fetch problem
  2. Copy exercise and test fs files into the directory containing FSharpExercismSolutions
  3. Right click on fsproj and add the new files (I believe this step can be eliminated if you modify the fsproj to include all fs files using a wildcard)
  4. Code solution and run tests
  5. Copy final solution back to the exercism directory
  6. Submit solution

@Mousaka I would be curious to know if you tried this flow whether it works for you and if there are any Linux only pitfalls I didn't hit since I'm running on Windows.

** @Mousaka you asked what the difference between an fsproj and a sln are and they are ways to split up code. A sln is a larger component that can contain multiple fsproj's inside. One common setup for small projects is to have one sln and then one fsproj for the code and one fsproj for the tests. Fsproj's can have dependencies between them. You don't actually need a sln and can work with a bare fsproj, although Visual Studio prefers having a sln.

What is the long term vision for the track?

Microsoft has historically been a very Windows-centric company and the older implementations of .NET reflect that. You can get them to run on Linux but it requires a lot of manual tweaking and effort. However, recently Microsoft has changed and have started investing in cross platform which includes the .NET core @ErikSchierboom referred to. .NET core is something that's been designed from the ground up with non-Windows platforms in mind, they're not just an afterthought.

@ErikSchierboom has done an incredible job at migrating the C# track to using .NET core including a sample csproj (the fsproj equivalent for C#) for every exercise. That prevents people from having to write the boilerplate code that you do today. The workflow for people in the C# track is:

  1. Fetch problem
  2. Open csproj
  3. Code solution and run tests
  4. Submit

We want to get there with the F# track as well, but unfortunately it's not free. @ErikSchierboom could give a better estimate on how long it would take to do this, based on his experience doing it with the C# track, but it's something measured in days or weeks not minutes or hours is my guess.

@kytrinyx asked if .NET core would take a lot of work to setup each problem and the answer is no. After the initial investment to get .NET core setup, creating a new problem is not a lot of work. I just added a new exercise in the C# track which you can see here:
exercism/csharp#378

The boilerplate code is the csproj which was a copy/paste from another exercise just renaming the file.

@rmunn
Copy link
Contributor

rmunn commented Aug 21, 2017

Here's the process I use on Linux:

  1. I have a private BitBucket repo containing my code, checked out to ~/exercism/fsharp/.
  2. I have a two-line bash script called doit.sh in that folder, which looks like this:
    #!/bin/bash
    xbuild exercise.fsproj
    nunit-console bin/Exercise.dll
  3. I have a paket.dependencies file in ~/exercism/fsharp that looks like this:
    source https://www.nuget.org/api/v2
    nuget FSharp.Core
    nuget NUnit
    nuget NUnit.Runners
    
  4. I have an exercise.fsproj file that looks like this:
    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <ProductVersion>8.0.30703</ProductVersion>
        <SchemaVersion>2.0</SchemaVersion>
        <ProjectGuid>{116CC2F9-F987-4B3D-915A-34CAC04A73DA}</ProjectGuid>
        <OutputType>Library</OutputType>
        <RootNamespace>Exercise</RootNamespace>
        <AssemblyName>Exercise</AssemblyName>
        <Name>Exercise</Name>
        <TargetFSharpCoreVersion>4.4.1.0</TargetFSharpCoreVersion>
        <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
        <MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
        <OutputPath>bin</OutputPath>
        <PlatformTarget>x86</PlatformTarget>
    </PropertyGroup>
    <ItemGroup>
        <Reference Include="mscorlib" />
        <Reference Include="System" />
        <Reference Include="System.Core" />
        <Reference Include="FSharp.Core" />
        <Reference Include="nunit.framework">
        <HintPath>..\packages\NUnit.Runners\tools\nunit.framework.dll</HintPath>
        </Reference>
    </ItemGroup>
    <ItemGroup>
        <Compile Include="HelloWorld.fs" />
        <Compile Include="HelloWorldTest.fs" />
    </ItemGroup>
    <Choose>
        <When Condition="'$(VisualStudioVersion)' == '14.0'">
        <PropertyGroup>
            <FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
        </PropertyGroup>
        </When>
        <Otherwise>
        <PropertyGroup>
            <FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
        </PropertyGroup>
        </Otherwise>
    </Choose>
    <Import Project="$(FSharpTargetsPath)" Condition="Exists('$(FSharpTargetsPath)')" />
    </Project>

The first step in making this all work is to download Paket and run paket install from the main ~/exercism/fsproj folder, so that I get the packages/NUnit.Runners/tools/nunit.framework.dll file that the .fsproj refers to. Then my process goes like this for each new exercise:

  1. cd ~/exercism/fsharp
  2. exercism fetch fsharp
  3. Figure out which exercise was downloaded. For this example, let's say it was the "Dominoes" exercise.
  4. cd dominoes
  5. cp ../hello-world/exercise.fsproj .
  6. Edit the local copy of the exercise.fsproj file and search-and-replace, changing HelloWorld to Dominoes. Since I use VS Code, I find it simplest to double-click on the text HelloWorld, hit Ctrl+D until all occurrences of that text have been selected, and then type the word Dominoes once, so it's edited everywhere.
  7. In some cases, I have to add or remove one character in the name of the unit-tests file. (Some exercises have FooTest.fs, and some have FooTests.fs.) Not a big deal, just something to watch for.
  8. Now I open DominoesTest.fs and README.md, and create Dominoes.fs, and start working on the exercise.
  9. When I think I've got it, I go to the command line and run ../doit.sh. Then if there are any compilation errors or failed unit tests, I fix the problem. If it compiled and ran fine, I run exercism submit Dominoes.fs and move on to the next exercise. (And I probably check my solution into Git and push it up to Bitbucket, so that I can work on the next exercise on a different computer if I need to).

@ErikSchierboom
Copy link
Member

There is indeed a bit of a learning curve, as well as some manual stuff you have to do at the moment. However, as @robkeim said, we are planning to move to .NET Core which will alleviate most if not all problems. The problem for a long time was: F# support on .NET Core was not in .NET Core 1.0, but with the recently released .NET Core 2.0, we can finally work on adding this integration. It is on the top of the list of the F# track's issues.

@ErikSchierboom
Copy link
Member

FYI: I've started working on this

@kytrinyx
Copy link
Member Author

@ErikSchierboom if you're able to describe it in a way where people could pick off specific pieces I could write about it in the next newsletter and tweet about it and maybe we could get people to help pitch in.

@ErikSchierboom
Copy link
Member

@kytrinyx Well, it's a bit hard as there is a fixed order and most of it is bulk updates. But I'll think about it! Thanks for the offer.

@rebelwarrior
Copy link

rebelwarrior commented Aug 21, 2017 via email

@ErikSchierboom
Copy link
Member

Well, it is not .NET Core per se, I have not phrased it correctly. What we are doing is moving to .NET Standard 2.0, of which .NET Core 2.0 is one of the runtimes. The benefit of moving to .NET Standard 2.0 are many:

  • The F# track then runs on the full .NET Framework, Mono and any machine that can run .NET Core 2.0
  • We can use the updated .fsproj file format, which is much cleaner and easier to edit
  • We can write instructions for the track using the .NET CLI, which runs on all .NET Core platforms so we only have to write the documentation for one use case

I hope I have explained things better. Mono will thus still be a completely viable runtime to use for the F# track.

@Mousaka
Copy link
Contributor

Mousaka commented Aug 22, 2017

@robkeim Thanks for your reply and for trying to help me out.

@Mousaka I would be curious to know if you tried this flow whether it works for you and if there are any Linux only pitfalls I didn't hit since I'm running on Windows.

Improved solution 1

I did not try your workflow but I tried something similar inspired by what you told me about how solutions-project-structure work:
Using Rider IDE (prob works with any other as well)

  1. I made a solution in exercism/fsharp (only needed one time, 2-4 is per problem)
  2. Created a new project for example "sum-of-multiples" in that solution
  3. Did exercism fetch fsharp sum-of-multiples
  4. Added the test-file and rename sum-of-multiples.fs to SumOfMultiples.fs (and maybe some namespace editing)

This made things a bit smoother but still too much hassle in my opinion. At least there is no need of moving around files after fetching or before submitting...

Improved solution 2

Inspired by @rmunn 's solution I did something similar with some additional scripting...
Followed your steps:

  1. I have a paket.dependencies file in ~/exercism/fsharp that looks like this:
source https://www.nuget.org/api/v2
nuget FSharp.Core
nuget NUnit
nuget NUnit.Runners

and

The first step in making this all work is to download Paket and run paket install from the main ~/exercism/fsproj folder, so that I get the packages/NUnit.Runners/tools/nunit.framework.dll file that the .fsproj refers to.

NOTE: My nunit.framework.dll did not have the same path as yours, mine was ..\packages\NUnit\lib\net45\nunit.framework.dll

Then when fetching a new problem I can use my script -> https://gist.github.com/Mousaka/f3b4127d93b73279515d1343d693df3a and a required template fsproj file (mostly copied from the one @rmunn posted but I did some fiddeling with it) -> https://gist.github.com/Mousaka/c5d03a02faa2428eafe36db28bb60be4

 ./helpInit sum-of-multiples

and it will fetch the F# problem from exercism and setup the problem directive to be a fsproject

exercism/fsharp
├── helpInit
├── paket.dependencies
├── paket.exe
├── paket.lock
├── sum-of-multiples    <-- Script generates this folder and all it's content as seen here
│   ├── build.sh
│   ├── README.md
│   ├── SumOfMultiples.fs
│   ├── SumOfMultiples.fsproj
│   └── SumOfMultiplesTest.fs
└── template.fsproj

The build.sh file is the equivalent of @rmunn doIt.sh but I used msbuild instead of xbuild because warnings said xbuild is deprecated and I that I should. I also had to install and use nunit3-console.exe (which I after installing renamed to nunit3-console) instead of nunit-console which where throwing exceptions because of some incompatible versions of NUnit or something... Another pitfall was installing paket which seems to have some issues with the official Linux tutorial -> fsprojects/Paket#2579
Came around that by just just downloading the latest paket.exe from github and used mono paket.exe install to install it.

This hacky solution took a while to make but after initial setup I can use this workflow for every new problem:

  1. (being in exercism/fsharp) ./helpInit sum-of-multiples
  2. code my solution in file SumOfMultiples.fs (in any text editor / IDE)
  3. run the build script that builds project and runs test
  4. User exercism submit fsharp sum-of-multiples/SumOfMultiples.fs when finished.

Thoughts

My experience with F# on linux so far is that following different setups and tutorials are often not that straight forward at this point in time. There are many pitfalls and many inconsistencies. Depending on when you try to install the tooling by following instructions versions may have changed and the only possible way of installing something might not be what the "Getting started" page says anymore.

Though I've learned a lot struggling the past days and I'm now able to start with my exercism problems it REALLY glads me to hear that @ErikSchierboom, and hopefully others too, are working on creating a better future for F# and surrounding tooling in the land of Linux =) thank you

@petertseng
Copy link
Member

petertseng commented Aug 22, 2017

In case it can be helpful, I share what I did to work on the F# track. These instructions are confirmed to work as of the time of writing this comment.

Here is the Vagrantfile I used:

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure('2') do |config|
  config.vm.box = 'ubuntu/xenial64'
  # Hey why not put C# on too, since we have Mono ready to go...
  config.vm.synced_folder '../csharp', '/vagrant_csharp'
  config.vm.provision 'shell', inline: <<-SHELL
    ln -s /vagrant /home/ubuntu/fsharp
    ln -s /vagrant_csharp /home/ubuntu/csharp
    apt-get update
    apt-get install -y mono-devel fsharp nunit-console
  SHELL
end

Here is the test.sh I use.

#!/bin/sh

set -e

if [ $# -eq 0 ]; then
  srcfile=$(ls -1 *.fs | grep -v Test)
  if [ -z "$srcfile" ]; then
    echo "found no .fs files, run in a directory with one, or specify one."
    echo "usage: $0 [srcfile [testfile]]"
    exit 1
  fi
fi

if [ $# -lt 2 ]; then
  testfile=*Test.fs
  testdll="$(echo $testfile | cut -d. -f1).dll"
else
  testfile=$2
  testdll="$(echo "$testfile" | cut -d. -f1).dll"
fi

srcdll="$(echo "$srcfile" | cut -d. -f1).dll"
nunit=/usr/lib/cli/nunit.framework-2.6.3/nunit.framework.dll

fsharpc -a $srcfile
fsharpc -a -r:$nunit -r $srcdll $testfile
nunit-console --noxml $testdll
rm $srcdll $testdll

Given that my Exercism directory is ~/exercism:

  • I place the Vagrantfile at ~/exercism/fsharp/Vagrantfile and the test.sh at ~/exercism/fsharp/test.sh
  • I run vagrant up in ~/exercism/fsharp (you can feel free to remove the two csharp lines from the Vagrantfile if you don't want them).
  • I fetch the exercises (using the host machine, so that I don't need to install exercism on the Vagrant machine)
  • I vagrant ssh onto the Vagrant machine and it's configured so that ~/exercism/fsharp/leap on the host machine becomes ~/fsharp/leap on the Vagrant machine.
  • I run test.sh on the Vagrant machine; the test should run and fail.
  • I complete the exercise using a text editor on the host machine (didn't want to install+configure a text editor on the Vagrant machine), meanwhile running test.sh on the Vagrant machine every so often to check my progress
  • submit when done (again, on the host machine).

@ErikSchierboom
Copy link
Member

@Mousaka If you're interested, you can follow progress on this issue on my branch: https://github.com/ErikSchierboom/fsharp/tree/dotnet-core

@Mousaka
Copy link
Contributor

Mousaka commented Aug 22, 2017

@petertseng I like how you use vagrant to make the installation setup more consistent. If someone would try my setup it's likely they're gonna run in to trouble. But in some way isn't it kind of a weird setup to have to run tests in a VM but code on host? I guess maybe it's kind of like having a build server you push changes to except that it's the only way to run tests.

@petertseng
Copy link
Member

But in some way isn't it kind of a weird setup to have to run tests in a VM but code on host

I guess I don't notice the difference because it's all in a terminal no matter whether it's on the host machine or the VM. It is possible I accidentally try to start up my text editor in the VM or test.sh on the host machine, but rare.

@ErikSchierboom
Copy link
Member

@Mousaka With #348 merged, the F# track should be a lot easier to get started with. It is all based on .NET Core now, so you are able to work on the track from a wide variety of platforms using either an IDE or the command-line interface.

@Mousaka
Copy link
Contributor

Mousaka commented Sep 4, 2017

@ErikSchierboom Great job! I will try it out. I saw the PR you merged.. it looked like a lot of work.. so.. Really awesome that you did all that for all the F#-curious people out there!! thank you so much 🎊 👍

@Mousaka
Copy link
Contributor

Mousaka commented Sep 4, 2017

Really easy to fetch problems and get going now!! Love it. You only have to type three commands to run tests now

exercism fetch fsharp
cd problem-folder
dotnet test

replace last command with something like <your_favourite_IDE> . to open the project in your IDE

@ErikSchierboom
Copy link
Member

@Mousaka Thanks for testing! Great to hear it works :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants