F#, Linux and makefiles - linux

I intend to distribute an F# program as both binary and source so the user has the option of recompiling it if desired. On Windows, I understand how to do this: provide .fsproj and .sln files, which both Visual Studio and MSBuild can understand.
On Linux, the traditional solution for C programs is a makefile. This depends on gcc being directly available, which it always is.
The F# compiler can be installed on Linux and works under Mono, so that's fine so far. However, as far as I can tell, it doesn't create a scenario where fsc runs the compiler, instead the command is mono ...path.../fsc.exe. This is also fine, except I don't know what the path is going to be. So the full command to run the compiler in my case could be mono ~/FSharp-2.0.0.0/bin/fsc.exe types.fs tptp.fs main.fs -r FSharp.PowerPack.dll except that I'm not sure where fsc.exe will actually be located on the user's machine.
Is there a way to find that out within a makefile, or would it be better to fall back on just explaining the above in the documentation and relying on the user to modify the command according to his setup?

If you don't want to use autoconf just write up README and say us how to setup tools to compile your program.
For example, you can require as to use binfmt_misc kernel module to allow system to automatically use right starter program for files with known format as to $PATH must contain path to fsc.exe, so your Makefile simply will be like following code:
FILES=types.fs tptp.fs main.fs
target.exe: ${FILES}
fsc.exe -o $# ${FILES} -r FSharp.PowerPack.dll
Or you can allow user to point to compiler by using makefile variables:
MONO=/usr/bin/mono
FSC=/usr/local/fsharp/bin/fsc.exe
COMPILER=${MONO} ${FSC}
FILES=types.fs tptp.fs main.fs
target.exe: ${FILES}
${COMPILER} -o $# ${FILES} -r FSharp.PowerPack.dll

Related

How to set LD_LIBRARY_PATH from a CMake toolchain file?

On Linux, I want to create a CMake toolchain file for cross-compilation.
The compiler needs some shared libraries that are located in non-standard directories, so I have to set LD_LIBRARY_PATH before invoking it. That worked when calling the compiler from the command line, but not when calling it from CMake.
I tried to set LD_LIBRARY_PATH via set(ENV{LD_LIBRARY_PATH} "${CMAKE_CURRENT_LIST_DIR}/<shared library directory>") from the toolchain file. However the compiler complained that it couldn't find the shared libraries.
Table of contents:
Setting it in a toolchain file isn't going to do what you want.
I'm not sure why setting LD_LIBRARY_PATH before invoking the buildsystem isn't working for you.
There's a more idiomatic way in CMake to do what you want.
Setting it in a toolchain file isn't going to do what you want
I'm pretty sure the approach you are asking how to take won't work because set(ENV) just sets an environment variable that will only be known to CMake at the configure stage (not the build stage). Here's a minimal reproducible example of that:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.23)
project(Foo)
set(ENV{FOO} "hello world!")
message("\$ENV{FOO} at configure time: $ENV{FOO}")
add_custom_target(echo
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_SOURCE_DIR}/echo.cmake"
VERBATIM
)
echo.cmake:
cmake_minimum_required(VERSION 3.23)
message("\$ENV{FOO} at build time: $ENV{FOO}")
run the following:
$ cmake -S . -B build --fresh
<...>
$ENV{FOO} at configure time: hello world!
<...>
$ cmake --build build/ --target echo
$ENV{FOO} at build time:
Since environment variables are "passed downward" to child processes and not upward, when you do set(ENV), that's just setting it in the CMake process that performs the configure step (the one invoked by the cmake -S ... command in the example above). As the example shows, CMake doesn't do anything fancy to make those environment variables known at its configure time to the generated buildsystem at build time.
I'm not sure why setting LD_LIBRARY_PATH before invoking the buildsystem isn't working for you
So I have to set LD_LIBRARY_PATH before invoking it. It works when calling the compiler from the command line, but not from CMake.
As long as you're exporting the variable for it to be made available to the shell's child processes (using the correct mechanism for whichever shell you're using), that should work. A minimal reproducible example would help here.
There's a more idiomatic way in CMake to do what you want
Try using the find_library() command. It does what its name says it does at configuration time (instead of build time). If you use it, you'll also get the benefit of your buildsystems being more cross-platform.
It has several ways of tweaking how it searches for libraries. You can read about exactly how it works in the official docs.
For your case here, one of the suitable configuration points to guide the library search would be the CMAKE_LIBRARY_PATH variable, although as you'll read about, there are other configuration points you could use as well.

Bash command: export BLAS_LIBS="-L$LAPACKHOME/lib -lblas"

Can any body explain to me what does the whole sentence mean?
I know this is to set Macro BLAS_LIBS as another string.
But I'm not sure what's the "-lblas" mean and I don't know how to use it.
Similar as the following code. "-llapack"
export LAPACK_LIBS="-L$LAPACKHOME/lib -llapack"
How can the program find out the BLAS and LAPACK libraries just by "-lblas" and "-llapack" ?
Thanks for advance.
I'm not sure why you say "just by -llapack" because that's not what is happening here. Specifically, the -L option just before it specifies a directory path to add to the library resolution path. This works roughly like PATH in the shell.
For example, with the command line fragment gcc -Lfoodir -Lbardir -lfoo -lbar, you basically instruct the linker to search the directories foodir and bardir for the library files libfoo.a and libbar.a.
The -l option is described in GCC: Options for Linking and -L and friends in the following section GCC: Options for Directory Search.
This build arrangement -- configure the build to show where the required files are before compiling -- is common for libraries, where if a user has already downloaded and compiled a required library for some other project, they don't need to rebuild it; they can just point the compiler to wherever they already have the stuff needed for this project.
Building your own libraries is becoming increasingly unnecessary anyway, as prepackaged binaries of most common libraries are available for most systems these days. But of course, if you are on an unusual platform, or have specialized needs which dictate recompilation with different options than any available prebuilt binary, you will still need to understand how to do this.

How to compile vim 64-bit on windows using MinGW-64?

I tried to compile vim 64-bit on windows. But I don't know how to use MinGW-64. There's a mingw-32-make in the 32-bit version, which I could use to build. But I didn't find any 'make' program in the 64-bit MinGW. Could you please tell me how to use mingw-64, or any tutorial I could follow?
Thank you.
It does not matter from which source make program comes, it only just must be able to execute the Makefile. To compile vim with MinGW with specific compiler and Make_ming.mak makefile I used to use the following:
Export environment variable CC set to the appropriate compiler (in my case it was 32-bit named i686-pc-mingw32-gcc).
Export environment variable LD set to the appropriate linker (in my case it was similar, but with -ld suffix in place of -gcc). Be sure they are found on $PATH: I am not sure what kind of escaping you should do to make makefile work so just avoid the necessity for escaping.
Export environment variable prefix pointing to the directory where mingw resides (in my case it was /usr/i686-mingw32: I am cross-compiling).
Export environment variable vim_cv_toupper_broken set to yes. I am not sure why I did this.
Finally run make:
cd {path/to/vim/repository}/src
make -f Make_ming.mak FEATURES=HUGE CROSS_COMPILE=i686-pc-mingw32- OPTIMIZE=SPEED VIMRUNTIMEDIR="C:\\vim73\\runtime" CROSS=yes ARCH=i686
. You definitely do not need CROSS_COMPILE and CROSS options and ARCH should be probably omitted (or equal to x86_64). VIMRUNTIMEDIR should point to the place where you plan to install vim. Not sure about escaping though.
Exporting environment variables should be probably done with
set var=value
, e.g.
set CC=x86_64-w64-mingw32-gcc
(use actual name of the executable). If this does not work try moving them to the make command line:
make -f Make_ming.mak CC=x86_64-w64-mingw32-gcc LD=… …
.
And variables for python (should also be present on the command-line):
PYTHON="P:\\ath\\to\\directory\\with\\python" PYTHONINC="P:\\ath\\to\\directory\\with\\python\\header\\files" PYTHON_VER=27 PYTHON_VER_LONG=2.7.5
. (If using python msi installer PYTHONINC is %PYTHON%\\include. It is 90% some directory whose trailing path component is include. Should contain at least Python.h file.)
I just compiled VIM on MinGW and made a gist about it. I tried x86-64 (search for it), too, and with /etc/fstab changed to 64 it basically worked, just that my interpreters all were 32 and so it stopped there.
Try to set
ARCH=x86-64 in vim74/src/Make_ming.mak
and add option CC=x86_64-w64-mingw32-gcc, maybe it will be useful.

Using GNU C++ built library in VS C++ project

I'm trying to implement an open source library that is built using the GNU compiler. (namely, this: https://github.com/mjwybrow/adaptagrams )
I've tried opening and building that source code using VSC++ 6, but it results in over a thousand errors due to the strict nature of the VS compiler I guess. And rather then go through every error and try fix it myself, I was wondering if it's possible to just include the .lib if it is built with the GNU compiler?
EDIT:
Included in the source code linked above is an autogen.sh file.
mkdir -p m4
autoreconf --install --verbose
automake -a --add-missing
./configure
make
Running that with Cygwin results in a few .a library files to be created, which are unusable in VS. Is it ok to just rename these to .lib files?
I've found some stuff online about how to use GCC and create a DLL, but my problem is that I don't know enough about the GNU compiler or makefiles, or the source code in general to be able to change it right now.
Does anybody have any clues on what exactly I'd need to change to get it right? Or even better, has anyone created a DLL using this source code already that would be able to pass it on to me, or let me know what I have to do?
Or could anyone point me towards a similar library that would be compatible with visual studio?
No; you can however build the .dll file with gcc and use the .dll from msvc (with either a hand-crafted include file or a properly formatted one from the beginning, with platform specific import/export macros on top).

Compiling Haskell code in Cygwin, and some other bugs in Haskell Platform on Windows

I am trying to compile a simple hello world program in Haskell, with Haskell Platform 2011.2.0.1. If I load the code in WinGHCi, and use the GUI to compile, the .exe is created. Then I can run the .exe from Cygwin.
But if I try to compile the code in Cygwin (using ghc --make), linker fails. But again, if I compile from the Windows cmd prompt, then the compile+linker works fine.
Are there any other environment variables I need to import into Cygwin, to make the compile+linker work in it? I have put the following dirs in my Cygwin PATH: 2011.2.0.1/lib/extralibs/bin, 2011.2.0.1/bin (these are the only two valid Haskell related entries that I could see in the Windows environment variables).
I also noticed a couple of invalid items in the Windows environment variables (this looks like a bug in the Haskell installation):
(system var) C/ProgramFiles/Haskell/bin - this dir does not exist because I have installed Haskell in D disk.
(user var) userxxx/ApplicationData/cabal/bin - this dir does not exist.
I tried to file a bug report in HaskellPlatform, but I dont have permission to do it.
Without access to your development environment or a listing of the errors that you're getting, I can only assume that the issue is related to the way that you've set up your PATH.
GHC on Windows comes bundled with its own gcc compiler (for C code) and ld linker. If you've installed Cygwin, you've probably also installed the MinGW toolchain, which comes with its own version of gcc and ld. Then, you've probably made your PATH variable list /usr/bin before the path to the Haskell Platform binary directories, which makes ghc find the MinGW linker and C compiler before it finds the versions that were bundled with GHC.
You need to make sure that the HP directories are listed before the Cygwin directories. It should not be like this:
$ echo $PATH
/bin:/usr/bin:.../2011.2.0.1/bin
Instead, it should be like this:
$ echo $PATH
.../2011.2.0.1/bin:/bin:/usr/bin
This is only a guess at what the issue might be, and you should provide more details for a better diagnosis.

Resources