Distributing gfortran-compiled binary to Mac OS X users who don't have Xcode? - gfortran

I'm teaching a class in which I would like students to run a precompiled command-line program on their own laptops. Some students have Windows; others have Mac. I was able to create a self-contained binary that the Windows users can just drop into their working directory and run.
To my surprise, I'm finding it far more difficult to do the same thing for Mac users. In particular, it appears to be impossible to compile a standalone binary program with all required libraries statically linked. The particular libraries that need to be present are libgfortran and libquadmath, since the gfortran compiler is used to compile the legacy F77 code (and it's too big a program to convert to another language).
So the only potentially workable solution I've found so far is for students to first install Xcode, then Xcode's command line tools, and finally gfortran on their own computer before my executable will find the gfortran library and run. But this is way too much work (and disk space) for what I want them to do.
My question: is there a way I'm overlooking to compile my program in completely self-contained form? Obviously it's hard for me to experiment, because it involves other people's computers.
EDIT: I found the following post which describes essentially the same problem: https://groups.google.com/forum/#!topic/comp.lang.fortran/TPEQQEwa0HI
Unfortunately, the solution given doesn't work for me, even after I delete some options and make appropriate substitutions.

The solution you linked to includes the -static-libgfortran, but not -static-libgcc, so it may be worth adding the second of these.
For a barebones Hello World code, I get:
[~] oldrabbit $ otool -L a.out
a.out:
/usr/local/opt/gcc/lib/gcc/8/libgfortran.5.dylib (compatibility version 6.0.0, current version 6.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
/usr/local/lib/gcc/8/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/local/opt/gcc/lib/gcc/8/libquadmath.0.dylib (compatibility version 1.0.0, current version 1.0.0)
[~] oldrabbit $ gfortran -static-libgfortran -static-libgcc hello.f90
[~] oldrabbit $ otool -L a.out
a.out:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
/usr/local/opt/gcc/lib/gcc/8/libquadmath.0.dylib (compatibility version 1.0.0, current version 1.0.0)
so looks like the libquadmath library might still be a problem. If you can find the path to the .a version of that, you could try including it like in the example you linked to.

a solution would be to ship the executable and the libquadmath by using install_name_tool:
cp -f /usr/local/Cellar/gcc/10.2.0_4/lib/gcc/10/libquadmath.0.dylib .
install_name_tool -change $i #executable_path/libquadmath.0.dylib a.out
Of course the second command must be done every time you recompile your binary

Related

How to build clang with the memtag sanitiser enabled

I have spent a few hours trying to get the built-from-sources version of clang (v15) to work with the memtag sanitiser. For those of you who don't know what that is, it is simply a version of the address sanitiser that leverages the Memory Tagging features of ARM.
Anyway, while I can use it normally with the repository version of clang (v10), using the version built from sources just does not work.
Here is the command I use for both: clang main.c -S -march=armv8+memtag -fsanitize=memtag with clang which is either the repository-version or the built-from-sources version. Although the former works seamlessly, the latter does not.
I've tried to built llvm with different parameters, but none seemed to have done the trick. Here's my current building configuration:
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;lldb;openmp;polly;pstl;compiler-rt" -DLLVM_TARGETS_TO_BUILD="AArch64" ../llvm
I wonder if there is some parameter I have to specify to build clang with this sanitiser enabled.
PS: using the -fsanitize=memtag flag does not give any error: with the built version of clang it simply does not insert the instrumentation code.
If anybody is able to give me some insight I would really appreciate it. Thanks ;)

clang/llvm compile fatal error: 'cstdarg' file not found

Trying to convert a large gcc/makefile project into clang. Got it roughly working for x86, but now I'm trying to get cross compilation working.
The way it currently works is that we use Linaro's 7.1.1 arm compiler alongside its companion sysroot directory for base libraries/headers. I installed clang-6.0 and then the base clang(not sure if that mattered).
I used some commands I found to redirect clang to clang-6.0 and when I execute 'clang -v' and got
clang version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
....
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/9
....
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/6.5.0
....
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0
Candidate multilib: .;#m64
Selected multilib: .;#m64
It does not find the current compiler we use which is at
/usr/local/gcc-linaro-7.1.1-2017.08-i686_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++(also a directory for *x86_64*)
I only found references to setting --sysroot, but not to a specific compiler. Definitely still lost about the relationship between clang+llvm+other compilers. I even saw somewhere saying I needed to compile llvm before I could use it?
I very roughly made changes in our make files to get the following output, basically all I had to add was '-target arm-linux-gnueabuhf' and reordered the mcpu/mfloat/marm/march so they came after -target in case it mattered
clang --sysroot=/usr/local/sysroot-glibc-linaro-2.25-2017.08-arm-linux-gnueabihf -c -std=c++0x
-g -DDEBUG_ON -target arm-linux-gnueabihf -mcpu=cortex-a7 -mfloat-abi=hard -marm -march=armv7ve
-Wall -fexceptions -fdiagnostics-show-option -Werror .... -I/usr/local/gcc-linaro-7.1.1-2017.08-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/include .... and many more
I think the problem probably lies with the change I made which is the actual 'clang' call that replaced
/usr/local/gcc-linaro-7.1.1-2017.08-i686_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ ....
End up with
fatal error: 'cstdarg' file not found
#include <cstdarg>
As said before I can already cross-compile with gcc, so I've already come across issues with std libraries that require 'build-essentials', 'g++-multilibs', etc. So they're already installed.
Looked and really haven't found anything too useful to me, I'm on linux mint 18.3 and the closest things I found were issues people had on mac and windows.
So I came across some posts mentioning setting --gcc-toolchain=/your/choice/of/cross/compiler but they also mention it not working. I discovered that if you combine this with the installation of llvm-6.0-dev(or maybe llvm-6.0-tools, tools installed dev so not 100%) it at least worked for me.
Any compiler clang or gcc needs to know where a header file is defined. The standard headers, standard libraries, c-runtime, and libc are all packaged together for each target e.g., arm64, x86 in a directory called 'sysroot'. When we compile a program we need to pass the path to sysroot for a compiler to know where to look for standard headers during compilation, and where to look for common libraries (libc, libstdc++ etc) during linkage.
Normally when we compile a program for the same machine the compiler uses the standard headers available in '/usr/include' and libraries from '/usr/lib'. When cross-compiling programs we should supply the sysroot as compiler flag. e.g. gcc --sysroot="/path/to/arm64/sysroot/usr" test.cpp. Same for clang. Most often pre-packaged cross compilers come with a script/binary that has 'sysroot' path embedded into it. e.g., aarch64-linux-gnu-gcc (https://packages.ubuntu.com/xenial/devel/gcc-aarch64-linux-gnu).
... the closest things I found were issues people had on mac and windows.
On mac the clang compiler will have the similar configuration as linux. So the details you found there should be totally applicable to yours.
More details on sysroot and cross-compilation:
https://elinux.org/images/1/15/Anatomy_of_Cross-Compilation_Toolchains.pdf

R library breaks due to failure in loading dyld

I have installed r with Homebrew and installed the INLA package for spatial analysis.
Unfortunately when using this module I get the following error:
dyld: Library not loaded: /usr/local/opt/xz/lib/liblzma.5.dylib
Referenced from: /usr/local/Cellar/r/3.4.1_1/lib/R/lib/libR.dylib
Reason: Incompatible library version: libR.dylib requires version 8.0.0 or later, but liblzma.5.dylib provides version 6.0.0
I have already installed the xz library with Homebrew which installs liblzma, otool -L /usr/local/lib/liblzma.5.dylib returns:
/usr/local/lib/liblzma.5.dylib:
/usr/local/opt/xz/lib/liblzma.5.dylib (compatibility version 8.0.0, current version 8.3.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)
This seem to indicate that I have the required version despite the exception raised by r.
Any help solving this issue will be deeply appreciated.
I haven't been able to solve the problem with the Homebrew r, but I decided instead to install the packaged version of R from the CRAN website.
The libR.dylib from the package version does not seem to depend on liblzma.5.dylib. INLA then works without error.
Any answer that manages to use Homebrew r should probably be upvoted.
In my case a similar error was fixed by reinstalling xz with the commands below, then reinstalling the r package.
brew unlink xz
brew reinstall xz

Compiling COBOL program on mac yosemite 10.10.2

While I'm running my COBOL code:
$ cobc hello.cob
I'm getting an error:
clang: error: unknown argument: '-R/opt/local/lib'
(Today,) I installed GnuCOBOL as root with
$ port selfupdate
$ port install open-cobol
Yeah, this has to do with Apple aliasing gcc to clang, but clang isn't a drop-in replacement for gcc yet. So it breaks on a few things. There is no simple way to fix this. If you type gcc you get clang.
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix
I'm not going to list all the details here, (and I know links are frowned on here on SO, but the entire thread will need to be read to get to grips with this problem. (Scripts are involved that strip some arguments out).
There is very little the GnuCOBOL compiler authors can do about this. The Mac clang is actually defining GNUC as well, so the compiler code that tests for gcc features is currently ineffective, clang reporting itself as gcc. Under a real gcc, the run-path setting in the ELF output is necessary, so -R can't just be yanked out. I see this as slightly dirty pool on Apple's part, but, it is their system, to wall off as they see fit.
http://sourceforge.net/p/open-cobol/discussion/help/thread/e1b4af35/
Changes to GnuCOBOL will try and workaround the issue, but that may take a while to get out into the wild.

Errors when cross-compiling OpenSSL on OS X for iOS with Clang instead of gcc

I would like to cross-compile OpenSSL 1.0.1h for iOS on OS X without gcc installed by following instructions in the WWDC 2014 session 305 video and from the OpenSSL web site.
I unzip/untar and the switch from gcc to clang (almost) as suggested here.
OLD_LANG=$LANG
unset LANG
sed -i "" 's|\"iphoneos-cross\"\,\"llvm-gcc\:-O3|\"iphoneos-cross\"\,\"clang\:-Os|g' Configure
sed -i "" 's/CC= cc/CC= clang/g' Makefile.org
sed -i "" 's/CFLAG= -O/CFLAG= -Os/g' Makefile.org
export LANG=$OLD_LANG
Notice that I had to stick with the makedepend tool for otherwise already the make depend step will fail (as was also mentioned elsewhere). Installing that tool with brew install makedepend is not an issue for me (but installing gcc next to Clang would be). Now
./Configure iphoneos-cross
make depend
make
leads to warnings (during make depend) and errors (during make) about missing include files (such as stdlib.h). The typical include path passed to clang is apparently -I. -I.. -I../include.
I assume this is to related to clang not receiving specific C options by default, but if so, what is the most sensible way for making the compilation work e.g. by fixing the sed edits or by setting environment variables. (Currently I don't have any CC* environment variables set. There is e.g. /usr/include/stdlib.h on my system.)
I rarely use OS X C compilers on the command line and the solution is therefore not obvious to me.
UPDATE Here is the question in a more specific for whose valid answer will be awarded with a bounty: What specific edits (similar to the first code snippet above) have to be performed on the files in latest version of OpenSSL source code (e.g. openssl-1.0.1h.tar.gz) so that one can cross-compiles it by issuing commands similar to the second code snippet above for iOS 7 (soon iOS 8) architectures on OS X 10.9 with Xcode 5.1.1 (soon Xcode 6) installed, without gcc installed and with makedepend optionally installed?
First, you must make sure that the current Xcode developer directory is set:
xcode-select -p
This should output something like this:
/Applications/Xcode.app/Contents/Developer
If you want to change this, for example to switch between Xcode 6 and Xcode 5 (or if that command outputted a blank line), you would use xcode-select as follows:
xcode-select -s /Applications/OldXcode.app/Contents/Developer
With that done, next you will need to choose an SDK to use. Since you're trying to build for iPhone, it would be some version of the iPhoneOS SDK. You can find which version it will try to use by default using this command:
xcrun --sdk iphoneos --show-sdk-version
Which will output something like 7.1 . If you need a different SDK version, you can provide it by using the specific SDK name with the version, i.e. iphoneos7.1. This of course must already be installed in the version of Xcode that you selected with xcode-select.
So assuming you have all those ducks in a row, using that information to cross compile is pretty easy. For example:
make CC="$(xcrun --sdk iphoneos --find clang) -isysroot $(xcrun --sdk iphoneos --show-sdk-path) -arch armv7 -arch armv7s -arch arm64"
This will pass the CC commands through xcrun, with the arguments to use the current iphoneos SDK of the Xcode set by xcode-select, building using the SDK root as the sys root and building for architectures armv7, armv7s, and arm64. Building for the iOS Simulator would be similar to the above, but passing the iphonesimulator in place of iphoneos as the SDK, and setting the architectures to i386 and x86_64.
With that, things should pretty much just work and you may not need to do anything further -- unfortunately I'm not in a position to try this myself and I'm referring to notes from a previous project. You may run into subsequent issues that are specific to OpenSSL or it's build scripts.
Note that all of the above can be used to compile for MacOS X as well, obviously with different SDK and architecture values.
I don't know if it's exactly what you want... but I compile OpenSSL for iOS following this script:
https://github.com/x2on/OpenSSL-for-iPhone/blob/master/build-libssl.sh
and it's very straightforward...
anyways, this answer here can help somebody else looking for how to compile OpenSSL for iOS.

Resources