I would like to compile fortran code on mac such that it does not depend on any shared library. Ultimately, I want to be able to send the binary to other people and for it to just work (provided the processor has the right architecture). I noticed that g95 and ifort have a -static flag, which does not work on mac.
If I consider the following program:
program test
print *,'hello world'
end program test
and compile it with
ifort -static-libgcc -static-intel test.f90
The resulting binary still depends on a few shared libraries:
valinor:tmp tom$ otool -L a.out
a.out:
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 103.0.0)
/usr/lib/libmx.A.dylib (compatibility version 1.0.0, current version 315.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 124.1.1)
So is there a way to properly compile fortran code such that it does not depend on any shared library on mac?
Static libraries are difficult on Mac OS X by design.
See this post for more information on static binaries on Mac OS X.
In theory, you could build static libraries yourself and link against them. You'd have to fetch the C runtime library from Darwin and compile it, libgcc, and so on, statically. It will work, but it might involve some work.
The short answer is: you don't actually want full static linking on Mac OS X. Linking in static versions of some product-specific libraries is fair and good, but the system shared libraries are just that: shared libraries that you'll always find on any Mac, with guaranteed compatibility from Apple.
PS: You can get rid of libgcc_s by actually specifying -static-libgcc on your commande-line. Not that it's worth doing any way, but...
Related
I would expect to be able to statically link against a build of libc with debug symbols, then run my program through lldb.
otool -L <my binary>
makes it look like the only dynamically linked library (dll) is:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
Which I would guess is the libc dll is (though nm doesn't list everything I'd expect in libc). Maybe just some kind of stub loader.
In /usr/lib/ it seems that Apple does not supply a debug build of libSystem.
How do you debug libc on OSX (10.11.3)?
Possible duplicate of:
On Mac OS X, how can you get a debug build of System/LibC for source level debugging?
I'm having a hard time following your question, but there are certain points to be made which I think will cover what you're asking:
otool -L will show all dylibs that you are linking against.
/usr/lib/libSystem.B.dylib is an umbrella library that re-exports multiple dylibs, including libc (/usr/lib/system/libsystem_c.dylib). If you want to see what symbols are part of the system's C runtime, you will want to use nm on that dylib, not libSystem.
If you are statically linking in your own libc, then it won't show up in 'otool -L' because it's a static library and is thus part of your executable.
If you staticy linked your own libc into your executable, then using nm on your binary will possibly not show all the symbols you are expecting because the linker will optimize away dead code that is not needed by your executable. You can ensure that everything is added by using the -force_load option to ld. Check out the ld man page for more details on that.
I'm observing different linking behaviour between two machines when compiling a binary.
Each has the same GHC (7.8.3), same code, same flags (-Wall -O2), same libgmp (installed by Homebrew on each):
machine-one$ otool -L my-binary
my-binary:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
machine-two$ otool -L my-binary
my-binary:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
/usr/local/lib/libgmp.10.dylib (compatibility version 13.0.0, current version 13.0.0)
I can't for the life of me figure out why libgmp is linked dynamically on the second machine.
In terms of differences I've been able to recognize: GHC has been installed via the binary distribution for OS X on the first machine and Homebrew on the second. For C compilers, we have:
machine-one$ cc --version
Apple LLVM version 6.0 (clang-600.0.51) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix
machine-two$ cc --version
Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix
What typically determines the linking behaviour, and how can I enforce one linking method or the other?
EDIT: I've observed the same behaviour happening with zlib on yet another machine, so it's not a GMP-specific issue.
EDIT: I've plucked ghc --info from each of the machines, here they are for machine one and machine two. And here's the diff between the two as well.
EDIT: I've reinstalled ghc on machine two via the distribution binary, and sure enough libgmp is not dynamically linked when I recompile my binary. So it seems like this is related to installing GHC via Homebrew.
Still quite interested in what's going on exactly.
The crucial difference is that machine #2 has /usr/local/lib in the linker path, and is using brew's linker (/usr/local/Library/ENV/4.3/ld). ghc still uses an external linker, even if it isn't using the C backend for code generation, so you can combine Haskell code with code written in other languages (crucial for Haskell's many FFI bindings to third-party libraries). So you should really be asking the brew people why things get linked differently. It's not actually a ghc issue.
I'm trying to install GalSim on OSX Mavericks, using the anaconda python distribution, but keep running into the error:
Unable to build a python loadable module using the python executable:
/usr/bin/env python,
the library name libpython2.7.a,
and the libdir /Users/harrison/anaconda/lib/python2.7/config.
If these are not the correct library names, you can tell scons the
correct names to use with the flags EXTRA_LIB_PATH and/or EXTRA_LIBS.
the /usr/bin/env python is the anaconda one and there is indeed a libpython2.7.a in that libdir.
scons is installed via the conda package management system.
boost is installed manually as recommended via
./bootstrap.sh --with-python=/Users/harrison/anaconda/bin/python --with-python-root=/Users/harrison/anaconda/
./b2 -a link=shared
sudo ./b2 -a --prefix=/usr/local link=shared install
checking the version of python boost links to gives
$ otool -L /usr/local/lib/libboost_python.dylib
/usr/local/lib/libboost_python.dylib:
libboost_python.dylib (compatibility version 0.0.0, current version 0.0.0)
libpython2.7.dylib (compatibility version 2.7.0, current version 2.7.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
Is this correct (it doesn't seem so to me -- boost seems to be linking to the libpython2.7 in /usr/local/) and is this what is causing the problem installing GalSim?
Thanks
Ian
Full output:
$ scons
scons: Reading SConscript files ...
SCons is version 2.3.0 using python version 2.7.6
Python is from /Users/harrison/anaconda/include/python2.7
Using the following (non-default) scons options:
CXX = g++
These can be edited directly in the file gs_scons.conf.
Type scons -h for a full list of available options.
Using python = /usr/bin/env python
Using default PYPREFIX = /Users/harrison/anaconda/lib/python2.7/site-packages
Using compiler: /usr/bin/g++
compiler version: 4.2.1
Determined that a good number of jobs = 4
Checking for C++ header file fftw3.h... yes
Checking for correct FFTW linkage... yes
Checking for C++ header file boost/shared_ptr.hpp... yes
Checking for C++ header file TMV.h... yes
Using TMV_LINK file: /usr/local/share/tmv/tmv-link
-L/usr/local/Cellar/tmv-cpp/0.71/lib -ltmv -lblas
Mac version is 10.9
WARNING: The Apple BLAS library has been found not to be thread safe on
Mac OS version 10.7 (and possibly higher), even across multiple
processes (i.e. not just multiple threads in the same process).
The symptom is that `scons tests` will hang when running nosetests
using multiple processes.
If this occurs, the solution is to compile TMV either with a
different BLAS library (e.g. ATLAS) or with no BLAS library at
all (using WITH_BLAS=false).
Checking for correct TMV linkage... (this may take a little while)
Checking for correct TMV linkage... yes
Checking if we can build against Python...
Unable to build a python loadable module using the python executable:
/usr/bin/env python,
the library name libpython2.7.a,
and the libdir /Users/harrison/anaconda/lib/python2.7/config.
If these are not the correct library names, you can tell scons the
correct names to use with the flags EXTRA_LIB_PATH and/or EXTRA_LIBS.
Please fix the above error(s) and rerun scons.
Note: you may want to look through the file INSTALL.md for advice.
Also, if you are having trouble, please check the INSTALL FAQ at
https://github.com/GalSim-developers/GalSim/wiki/Installation%20FAQ
Ian, thanks for posting that. Based on the config.log and my own experience, I have an answer that should solve at least this problem (no guarantees that you won't hit something else later in the build).
The key problem here is that if you tell it the compiler is gcc (as is the default), it will try to use openMP. But actually invoking gcc on Mavericks gives you clang++, for which openMP doesn't work. So, you have to explicitly tell galsim that the compiler is clang++ so it won't try to use openMP. (The clue to this is in config.log, there are messages in various places about undefined symbols for x86_64 architecture... I had this problem on my own system when I started using Mavericks. See also https://github.com/GalSim-developers/GalSim/issues/493 )
So, please do scons CXX=clang++ and this problem should go away. I cannot guarantee that you won't hit a boost problem later on, however.
Please also see this question which has two suggestions which may help solve the problem for you as well.
My project is compiled with 10.6SDK and selected 10.5 as Deployment Target. When I run the binary in 10.5 leopard system it gives me
Symbol not found: __ZNKSt13bad_exception4whatEV
Referenced from: ......
Expected in: /usr/lib/libstdc++.6.dylib
Sometimes ago I got the same problem and I closed to use a boost header to make a solution but it was temporary solution. Why this happen? If this symbol is not in 10.5 system, why it compiles without problem?
I can't even find which library call this symbol (probably boost but where?)
Edit:
I found the guilty. thread.o compiled file call __ZNKSt13bad_exception4whatEV this symbol. I had updated boost library from 1.46 to 1.53. Before I had the same problem and I had changed:
#include <boost/thread.hpp>
to
#include <boost/thread/thread.hpp>
and the problem was gone. Now when I updated boost to 1.53, this is calling again.
I compiled boost with macports or with b2.
otool -L bin.v2/libs/thread/build/darwin-4.2.1/release/address-model-32_64/macosx-version-min-10.4/macosx-version-10.8/threading-multi/libboost_thread.dylib
bin.v2/libs/thread/build/darwin-4.2.1/release/address-model-32_64/macosx-version-min-10.4/macosx-version-10.8/threading-multi/libboost_thread.dylib:
libboost_thread.dylib (compatibility version 0.0.0, current version 0.0.0)
libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
I still see /usr/lib/libstdc++.6.dylib. That means it doesn't compatible with 10.5.
I also looked a solution for static link with libstdc++ but I cound't find it.
I am still looking a solution for it.
Edit2:
I think I give up. I don't have more time for this ridiculous situation. I don't understand why Apple don't supply a updated libstdc++ for 10.5 leopard system. There are so many problem with libstdc++ in 10.5.
The main question why Xcode did NOT tell me this binary is not compatible with 10.5 system?
Windows is much more well about backward compatibility. Now, I can even compile for xp sp3.
I use always staticaly link in Windows but in Apple this is imposible.
At this moment I have learnt that if I want to use c++11 features, I have to compile for 10.7 system. Not even for 10.6 system too. But in Professional Audio so many people use still 10.6 system. I have to wait to use c++11 because of Apple's non static link situation or Aplle's backward compatibility approach.
Yes, I am little bit angry!
I'm trying to link to a static library on OS X. I used the -static flag in the gcc command but I get the following error message:
ld_classic: can't locate file for: -lcrt0.o
collect2: ld returned 1 exit status
I looked in the man pages and it reads something like:
This option will not work on Mac OS X unless all libraries (including libgcc.a) have also been compiled with -static. Since neither a static version of libSystem.dylib nor crt0.o are provided, this option is not useful to most people.
Is there another way to link to this static library?
In order to link to an archive library (sometimes also called static library), just add it to the link line:
gcc main.o ... -lfoo ...
The linker will search for libfoo.dylib, and then libfoo.a, which is all you need.
If you have both versions of the library, and want to link with an archive version in preference of the dynamic one, just specify the full path to the archive on the link line:
gcc main.o ... /path/to/libfoo.a ...
Regretfully, it's not supported. Some people reported it's possible to manually compile crt0 but nobody confirms it.
A common case is to static link against a third user library while dynamically linking against the system frameworks and libraries, so your users don't need to install third party libs before using your program. If the library is dynamically linked against frameworks (as is often the case), it may still ship with a static .a, but it is not sufficient just to replace -l<libname> with /path/to/libname.a because the .a will not have the dependencies in it. You will also have to dynamically link against those frameworks that your library was using.
For example, say you want to write a program that uses the open source libusb without requiring your user to download and install libusb. Say you have a dynamically linked binary you built with this:
clang -lusb-1.0 main.c -o myprogram
To statically link on OS X, the command looks like this (note the -framework arguments):
clang -framework CoreFoundation -framework IOKit main.c /path/to/libusb-1.0.a -o myprogram
To find what system frameworks and libraries you need to add, look at the third party dylib using otool:
otool -L /usr/local/opt/libusb/lib/libusb-1.0.0.dylib
which shows:
/usr/local/opt/libusb/lib/libusb-1.0.0.dylib:
/usr/local/opt/libusb/lib/libusb-1.0.0.dylib (compatibility version 2.0.0, current version 2.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1348.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)
You can start by adding the frameworks, followed by the libraries one at a time and you will see the list of undefined reference errors shrink. Note you probably won't need to add every library, because some may be loaded as dependencies for the ones you explicitly added.
If you aren't sure where the dylib exists, build your program the original dynamic way (with -lusb-1.0), and run otool on it:
clang -lusb-1.0 main.c -o myprogram
otool -L myprogram
which gives:
myprogram:
/usr/local/opt/libusb/lib/libusb-1.0.0.dylib (compatibility version 2.0.0, current version 2.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)
Also, read the license of the library you are linking to.
-Bstatic seems to be a no-op on OS-X Lion - used gcc -v to confirm this.
I've been run into the same issue. Here is an example to work around:
STEP1: create files
myfunc1.c:
#include <stdio.h>
void myfunc1() {
printf( "This is my func1!\n" );
}
myfunc2.c:
#include <stdio.h>
void myfunc2() {
printf( "This is my func2!\n" );
}
and myfunc.c:
#include <stdio.h>
void myfunc1( void );
void myfunc2( void );
int main() {
myfunc1();
myfunc2();
return 0;
}
STEP2: create the lib
gcc -c myfunc1.c myfunc2.c
ar -r libmyfuncs.a myfunc1.o myfunc2.o
STEP3: link
gcc -o myfunc -L. myfunc.c -lmyfuncs
Do not forget to type "-L."; dot indicates the current path.
Hope that helps.