Use FORTRAN linker in cmake mixed language project - cmake

When CMake is used for a mixed language project (C/C++ and FORTRAN), the C++ compiler is called to link the executable. Is there an easy way to call the FORTRAN compiler for the linking step.
project(Serialbox_Fortran_Perturbation_Example CXX Fortran)
add_executable(main_producer main_producer.f90 m_ser.f90)
This will compile correctly with the FORTRAN compiler but for the linking step, the C++ compiler will be called and it causes trouble with some compiler suite like PGI for example.

As a workaround one can set the linker language explicitly:
set_property(TARGET your_target PROPERTY LINKER_LANGUAGE Fortran)
or play with CMAKE_<LANG>_LINKER_PREFERENCE (I haven't checked if the latter works now, it didn't work when I tried a few years ago).

I expect what you are seeing is that the linkage is executed through the GCC C++ frontend
with Fortran libraries added. To get the linkage done through the GCC Fortran frontend
this hack should do:
project(Serialbox_Fortran_Perturbation_Example CXX Fortran)
set(CMAKE_CXX_LINK_EXECUTABLE "gfortran <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
add_executable(main_producer main_producer.f90 m_ser.f90)

Related

Easy way to get cmake default compiler

I am new to cmake.
I have seen that doing export CXX=g++ tells cmake to use the g++ compiler for the .cpp files for instance.
I also read that if we don't pass any compiler with CXX, it will search for a compiler with name cc, gcc, cl, bcc, xlc, clang (in that order). But if we don't export any compiler, is there an easy command to know what compiler exactly cmake use for the .cpp files for instance? Will it always be g++ if we have it installed?
Turning my comment into an answer:
You can get the C and C++ compiler names from the variables CMAKE_CXX_COMPILER and CMAKE_C_COMPILER like gcc, g++, cl, or clang. With the variables CMAKE_C_COMPILER_ID and CMAKE_CXX_COMPILER_ID you get the identifier of the compiler like GNU, LLVM, or AppleClang.

Cmake: how to force it to use colormake?

in order to use colormake I did set this alias in my .bashrc
alias make="/usr/bin/colormake"
It works, as if I try to compile (with qmake) a simple C++ example code with errors (just a main.cpp with a cout ), they are correctly coloured.
However, if I compile the same code with cmake, colormake is not used. What can I do to force cmake to use it?
my minimal CMakeList.txt example is
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2)
ADD_DEFINITIONS(-std=c++11)
ADD_EXECUTABLE(exe main.cpp)
System: Debian 8.8 jessie
Thanks, Valerio
Update:
I modified the CMakeLists.txt in this way, but no success:
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2)
ADD_DEFINITIONS(-std=c++11)
set(CMAKE_MAKE_PROGRAM /usr/bin/colormake)
ADD_EXECUTABLE(exe main.cpp)
message("CMAKE_MAKE_PROGRAM: " ${CMAKE_MAKE_PROGRAM})
Update 2:
I modified the CMakeList in this way:
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2)
ADD_DEFINITIONS(-std=c++11)
#set(CMAKE_COLOR_MAKEFILE OFF)
#set(CMAKE_MAKE_PROGRAM /usr/bin/colormake)
ADD_EXECUTABLE(exe main.cpp)
message("CMAKE_MAKE_PROGRAM: " ${CMAKE_MAKE_PROGRAM})
message("CMAKE_COLOR_MAKEFILE: " ${CMAKE_COLOR_MAKEFILE})
then launched cmake with this argument from command line:
cmake -DCMAKE_MAKE_PROGRAM=/usr/bin/colormake -DCMAKE_COLOR_MAKEFILE=OFF ../
But again, the main.cpp synthax error after make is not coloured.
This is the output of cmake, note the messages about CMAKE_MAKE_PROGRAM and CMAKE_COLOR_MAKEFILE
-- The C compiler identification is GNU 4.9.2
-- The CXX compiler identification is GNU 4.9.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
CMAKE_MAKE_PROGRAM: /usr/bin/colormake
CMAKE_COLOR_MAKEFILE: OFF
-- Configuring done
-- Generating done
-- Build files have been written to: /home/valeriosperati/Desktop/VALERIO_SPERATI/prova_codice_c/colormake/cmake/build
Some additional (maybe helpful) info: this is the output
I obtain when compiling with qmake, the error 'hjskf' is in red.
this is the output when comiling with cmake:
It should be enough to set the CMAKE_MAKE_PROGRAM cache variable to point at the build tool you want to use. You can do this by running cmake with a -D option like so:
cmake -DCMAKE_MAKE_PROGRAM=/usr/bin/colormake path/to/src
For the benefit of others, this technique can be used with other generators too, not just make. Just be aware that it is your responsibility to make sure the build tool specified matches the generator type CMake is using (i.e. don't pass a make tool if you've told CMake to use Ninja with -G Ninja instead).
Note, however, that this only really matters if you are invoking the build via CMake like so:
cmake --build path/to/build/dir
Some IDE tools may invoke the build that way. Most of the time, however, developers invoke the tool directly. In your case, you can simply invoke colormake instead of make. If you are still not getting colored output after doing that, then your problem must be elsewhere (check your terminal type settings perhaps).

CMake to handle F77 and F90 files differently

I'm trying to port our project from autotools to CMake and got stuck on fortran compiler settings. The project consists of C++, Fortran and Fortran90 pieces. In our autoconf/automake project we have simply defined FC and F77 together with corresponding flags like FCFLAGS and FFLAGS. But in CMake it seems to work a bit differently.
What I did so far:
project (blah-proj CXX Fortran)
... in ibm case ....
set (CMAKE_Fortran_FLAGS "-qfullpath -qinitauto -qnolm -qinit=f90ptr -qfree=f90 " )
and in the source directory CMakeLists.txt:
file (GLOB_RECURSE libblah_f_sources *.f90 *.f)
add_library (blah_f ${libblah_f_sources})
set_target_properties (blah_f PROPERTIES LINKER_LANGUAGE Fortran)
With gfortran on linux it works fine as it's only one binary, but on AIX there are 2 different compilers called xlf and xlf90. Of course it doesn't work as CMake tries to compile both *.f and *.f90 files with same compiler.
It doesn't seem I got what I really wanted, but at least it solved the problem at the first approximation. I kept same structure but then I let compiler itself decide what kind of file it is. Of course I had to remove the version-dependent directives like -qfree=f90 or -qfixed=128 in the hope that compiler is smart enough to guess them from the file extension.

how can i generate 2 binaries, one in fortran and one in cxx, with cmake

I have a library that must be linked to 2 main codes, one in fortran and on in cxx.
I have this library in src/lib/CMakeLists.txt:
ADD_LIBRARY(mylib a.f90 b.c c.cc)
and in src/main/CMakeLists.txt, I have:
ADD_EXECUTABLE(mymain1 mymain1.f90)
TARGET_LINK_LIBRARIES(mymain1 mylib)
ADD_EXECUTABLE(mymain2 mymain2.cc)
TARGET_LINK_LIBRARIES(mymain2 mylib)
When compiling mymain1, it use the CXX compiler to link instead of the Fortran one.
How can I tell cmake to use Fortran to link mymain1 and CXX to link mymain2?
You may directly affect on language used for linking with LINKER_LANGUAGE property:
# Use Fortran compiler for link 'mymain1' executable
set_target_properties(mymain1 PROPERTIES LINKER_LANGUAGE Fortran)
Another way could be "teach" CMake to properly choose linker.
Without the library CMake would correctly select Fortran linker for mymain1 as it compiled only from Fortran sources, and C++ linker for mymain2 as it compiled only from C++ sources.
But linking with the library messes CMake: because the library mylib is compiled from sources on several languages, CMake selects linker for it using some "preference scores" for languages (see CMAKE_<LANG>_LINKER_PREFERENCE variable). More likely, C++ "beats" Fortran in your case.
Moreover, when select linker language for mymain1, CMake take into account language for the static library mylib. Because of that C++ wins even for the executable built from Fortran sources only.
You may disable propagating library's language to the executable using variables CMAKE_<LANG>_LINKER_PREFERENCE_PROPAGATES:
# <place this *before* adding executables>
# Do not propagate language of C++ libraries to the executables.
set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES OFF)

How to use CMake for Fortran and C++?

I am new to CMake and it seems really hard to get my script work. My codes can be compiled the usual way, but I really need to use CMake. I compiled with the following:
g++ vectc.cpp -c -std=c++11
gfortran vectf.f vectc.o -lstdc++
This CMakeLists.txt, that doesn't work for me:
cmake_minimum_required (VERSION 2.6)
project (add_vectors CXX Fortran)
enable_language(Fortran)
set(CMAKE_CXX_FLAGS "-c -std=c++11")
set(CMAKE_Fortran_FLAGS "CMakeFiles/executable/vectc.o -lstdc++")
add_executable( executable
vectc.cpp
vectf.f)
If I run make after cmake i get the following, and I really dont know what to do:
[ 33%] Linking CXX executable executable
c++: warning: CMakeFiles/executable.dir/vectf.f.o: linker input file unused because linking not done
c++: warning: CMakeFiles/executable.dir/vectc.cpp.o: linker input file unused because linking not done
[100%] Built target executable
Does anyone can help me with it?
Edit:
The comments shows, I did not asked well. I am pretty new to the Cmake, and I don't know why I got the warnings. Also I have not found my "executable" file.
Reformulating my previous comment as an answer:
In case of mixed language sources (CXX, Fortran) the CXX linker is used by CMake because its linker preference is higher than that of the Fortran linker. But because of the PROGRAM statement in the fortran source the Fortran Linker is needed. Setting the LINKER_LANGUAGE property by set_property(TARGET executable PROPERTY LINKER_LANGUAGE Fortran) gives CMake a hint to select the correct linker.