How to specify preference for compilers when using enable_language [cmake] - makefile

When using enable_language in cmake, it always search for compilers in a certain default sequence. I wonder how I can change this sequence. For example, if my system has both ifort (icc) and gfortran (g++) installed, and I want to use ifort (icc) instead of the gfortran (g++), how could I set up this?
CLARIFICATION: I know we can switch the compiler explicitly by changing the variable CMAKE_Fortran_Compiler, but what I want to do is rather to modify the default sequence that cmake searches for available compilers if the user does not specify such a preference.
From what I currently found, a work-around is to set CMAKE_Fortran_Compiler before project(xxx), so that this variable can never gets overridden later, but clearly this is not the best way, since I will need gfortran if there turns out to be no ifort available.
By the way, what's the best place to look for this kind of information? The documentation does not seem to be very complete..
Thanks!

The right place to look is the CMake FAQ, which answers your question.
Omegaice's answer will work, as will CC=/path/to/icc cmake ..., see also this discussion thread.
Setting CMAKE_Fortran_Compiler before the project call is strongly discouraged (as the FAQ will tell you).
Note that manually calling enable_language is no different from specifying the languages with the project call (or indeed not specifying them, in which case they default to C and CXX), since that calls enable_language internally.

You can probably specify which compiler to use by doing ccmake .. -DCMAKE_Fortran_Compiler=<executable> (where <executable> is either the name of the compiler or the full path to the compiler) instead of setting it in the CMakeLists.txt.

Related

Cmake change stack size

Is there a way to change stack size from the Cmake ?
I only found one forum thread mentioning CMAKE_CXX_STACK_SIZE but I couldn't find the documentation for this command. Ideally the command should work for both Visual Studio C++ and gcc.
I don't have VS at the moment, but the following three CMake commands all work for me on MinGW/GCC (replace <target> with what you entered into add_executable()):
target_link_libraries(<target> PRIVATE "-Wl,--stack,10000000")
OR
set_target_properties(<target> PROPERTIES LINK_FLAGS -Wl,--stack,10000000)
OR
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,10000000")
Note that according to the CMake documentation, each of these should just add linker flags, not replace any that are already set.
In VS, it looks like you should replace -Wl,--stack, with /STACK: (more on this below) and use an if/else to have different commands for each compiler.
Regarding CMAKE_CXX_STACK_SIZE, this thread, which is worth a read, says the command is
in the implementation of the VS generator for historical reasons but is not intended as a first-class way to set the stack size. Instead just pass /STACK:... as a linker flag using target_link_libraries, or the LINK_FLAGS target property, or in CMAKE_EXE_LINKER_FLAGS...
Such a command can actually be seen on the page linked in your post (not sure if you saw it) as well as in this one:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10000000")

setting up autotools to link single system library statically

I have a project, where I want to link one of system libraries statically. The project uses GNU build system.
In configure.ac I have:
AC_CHECK_LIB(foobar, foobar_init)
On development machine this library is installed in /usr/lib/x86_64-linux-gnu. It is detected, but it is linked dynamically, which causes issues, as it is not present on some machines. Linking it statically (-Wl,-Bstatic etc.) works fine, but I don't know how to set this up in autotools. I tried forcing this into Makefile.am link flags for the project, but it still gives a preference to dynamic library.
I also tried using --enable-static with ./configure, but it seems to have no effect on system libraries.
If you want to link the whole program statically, then you should pass the --disable-shared option to configure. You might or might not need also to pass --enable-static, depending on the default value for that option (which you can influence via your configure.ac file). You really should consider doing this.
You should also consider making this the installer's problem, not the build system's. Let it be the installer's responsibility to ensure that all the shared libraries needed by the program are provided by the systems where it is installed. This is very common; in fact, it is one of the inspirations for package-management systems such as yum / dnf and apt, and their underlying packaging formats.
If you insist on linking only one library statically, while linking everything else dynamically, then you'll need to jump through a few more hoops. The objective will be to emit link options that cause just that library to be linked statically, without changing other libraries' linking. With the GNU toolchain, and supposing that the program is otherwise being linked dynamically, that would be this combination of options:
-Wl,-Bstatic -lfoobar -Wl,-Bdynamic
Now consider the documentation of the AC_CHECK_LIB() macro:
Macro: AC_CHECK_LIB (library, function, [action-if-found],
[action-if-not-found], [other-libraries])
[...] action-if-found is a list of shell commands to run if the link with the library succeeds; action-if-not-found is a list of shell
commands to run if the link fails. If action-if-found is not
specified, the default action prepends -llibrary to LIBS and defines
'HAVE_LIBlibrary' (in all capitals). [...]
Note in particular the default behavior in the event that the optional arguments are not provided (your present case) -- that's not quite what you want, at least not by itself. I suggest providing at least an alternative behavior for action-if-found case, and you could consider also making configure fail in the action-if-not-found case. The latter is left as an exercise; implementing just the former might look like this:
AC_CHECK_LIB([foobar], [foobar_init], [
LIBS="-Wl,-Bstatic -lfoobar -Wl,-Bdynamic $LIBS"
AC_DEFINE([HAVE_LIBFOOBAR], [1], [Define to 1 if you have libfoobar.])
])
You should also pay attention to the order of your AC_CHECK_LIB() invocations. As its docs go on to say:
This macro is intended to support building LIBS in a right-to-left
(least-dependent to most-dependent) fashion such that library
dependencies are satisfied as a natural side effect of consecutive
tests. Linkers are sensitive to library ordering so the order in which
LIBS is generated is important to reliable detection of libraries.
If you find that you still aren't getting what you want, then have a look at the link commands that make actually executes. You need to understand what's wrong about them before you can determine how to fix the problem.
With all that said, I observe that the above treatment is basically a hack, and it makes your build system much less resilient. It introduces dependencies on GNU toolchain options (which some other toolchains may nevertheless accept), and it assumes dynamic linking is being performed overall. It may be possible to resolve those issues with additional Autoconf code, but I urge you to instead go with one of the first two alternatives I described.

Ccache doesn't work with gcc -M flag?

I'm trying to use ccache to speed up my rebuilds and I noticed this in the log:
[2015-04-17T10:41:45.845545 27682] Compiler option -M is unsupported
[2015-04-17T10:41:45.845584 27682] Failed; falling back to running the real compiler
In my experience you need something like the -M flag in order to have make or its equivalent trigger rebuilds correctly. It seems weird that ccache would be tripped up by an option that must be in almost every project's build. Am I missing something? Is there a more preferred option?
This is w/ ccache-3.2.1.
Edit: I tried with -MM as well, no luck.
It is correct that ccache currently doesn't support the compiler options -M and -MM (and it never has supported them).
Some reasons for why the options in question are unupported:
The options tell the compiler to let the preprocessor output make rules instead of the preprocessed source code. This is not a good match for how ccache works; it needs to get hold of the "real" preprocessed output for each compiler invocation (see https://ccache.dev/manual/3.7.11.html#_how_ccache_works).
Nobody has implemented support for the mentioned options, simply put.
It would most likely be possible to implement support by letting ccache run the compiler command twice: one without -M/-MM to retrieve the preprocessed source code (with which the result should be associated) and one with -M/-MM to retrieve the result (make rules).
However, I (speaking as the ccache maintainer for the last six years) have not heard anybody missing support for -M/-MM until now, so my impression is that -M/-MM actually aren't used much.
Am I missing something? Is there a more preferred option?
Yes, I would say that the standard way is to use -MD/-MMD (which are supported by ccache) instead of -M/-MM. -MD/-MMD are superior because they produce both the .o and the .d file in one go, whereas -M/-MM only produce the .d file, so the compiler must in that case be invoked twice by the Makefile for each source code file. See for instance http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html for how to use -MD/-MMD.

generic compilation time option in fortran

the compilation options are vendor specific (in my knowledge)
so, in makefile, I have to provide,
if FC=ifort
FFLAGS=<long list of options provided by intel>
else
if FC=gfortran
FFLAGS=<same list in gnu way>
end if
is there a way to specify a generic option? by generic, I mean, a vendor
independent way of specifying the options. I don't mind creating them
using autotools(i.e. autoconf, automake). but is there a way?
I am not sure, if this answers your question or provides you any help at all. But, what I use to allow activation of compiler options in a more generic way, is to define variables for specific features, for example warning, debugging, optimization and profiling, and set these according to the compiler currently used.
I am using waf for configuration and building, see for example this build script, where the FCFLAGS are set according to the configured compiler, with different options activated for the various build variants, that are available. I guess, you can do something similar with autotools, or pure make.

Environment variables that one should update when using a new compiler

Say a system admin provides a new version of the gcc compiler available on /some/path on a machine where I build software (all types of software including open source, 3rd party tools, my own programs, etc.):
I usually update the following three environment variables $PATH, $LD_LIBRARY_PATH and $MANPATH, according to what I understand is standard practice for interfacing with general building tools (e.g. autoconf, cmake, etc.) or scripts.
setenv MY_GCC /some/path
setenv PATH $MY_GCC/bin:$PATH
setenv LD_LIBRARY_PATH $MY_GCC/lib64:$LD_LIBRARY_PATH
setenv MANPATH $MY_GCC/share/man:$MANPATH
Here I have a quick question: is there really a reason to update LD_LIBRARY_PATH (why would programs link against a compiler?).
But more generally, what environment variables should one update upon the installation of a new compiler to guarantee a proper building environment?
It depends.
Generally, you do not need to set up any environment variables other than PATH to have a proper building environment (and if you use an IDE, not even that may be necessary, though you might have to tell the IDE where to find the compiler if it lives in an unexpected, non-standard location).
If you use something like autoconf (or CMAKE, or any similar thing), and especially if you have several compiler versions (or cross compilers) on the system, you may want to set variables like CC or CXX to a reasonable default just to be sure (and modify them accordingly if you want something else).
Though if your compiler has its target appended to its name (as in most builds), this is probably not necessary. At least, it works perfectly well for me without doing anything special.
If English is not your native language and your GCC was built with locale support (most stupid idea ever, if you ask me), you may want to set LC_ALL to "C". Otherwise you'll notice that your "unreadable" error messages won't get you much help if you ask for a compiler problem on a forum.
If you have a ramdisk (or SSD) in addition to a normal harddisk, but your projects are on the normal harddisk, you may want to set TMPDIR (even if you always compile with -pipe, since this sometimes seems to create temp files anyway for a reason I don't understand).
If you have non-standard locations for libraries that you want to use, you can set LIBRARY_PATH, but I advise against it. It is better to have your build scripts (or project settings in the IDE) such that these locations are given to the linker on the commandline (or passed through configure with something like --with-foo-path=...). This guarantees that your projects build everywhere and anywhere without requiring someone else to performa a magic dance with some unknown, obscure environment variables. The same goes for C_INCLUDE_PATH.

Resources