Correctly Building Fortran Libraries And Using Them To Build Applications - module

I found a few previous questions regarding this, but was unable to find something specific for advice on correctly associating libraries and module files *.mod in a Makefile.
I have a project directory named project where all source files for a library are in project/src, all compiled *.mod files are placed in project/include, and static libraries are created into the directory project/lib using the following:
ar rc myLibrary.a module1.o module2.o module3.o
Following this, I create an application code (a Fortran program that uses these libraries) in the directory project/applications. I have now, at the root level (that is, inside project) created a simple shell script that can build the application. This part is where I cannot get the process to work.
Here is what I am doing:
INCLUDELIB='./include'
LINKLIB='./lib'
INCLUDEOTHER=<include directories for other math libraries>
LINKOTHER=<link directories and link flags for other math libraries>
COMPILER='ifort'
COMPOPTS=<compiler flags, currently I use none>
# building the application:
$COMPILER $COMPOPTS -c ./applications/application.f90 -I$INCLUDELIB $INCLUDEOTHER -L$LINKLIB $LINKOTHER
$COMPILER $COMPOPTS application.o -I$INCLUDELIB $INCLUDEOTHER -L$LINKLIB $LINKOTHER -o application.out
This procedure does not work, and it gives Error in opening the compiled module file. Check INCLUDE paths.
I tried a few variants of the above from my readings on the web about this, and I hope that it is not some minor/silly error that I am overlooking that is leading to this.
Any help or advise will be much appreciated.

This is the message you get when things were not done right with the library (it's not your fault!).
*.mod files are compiler-specific, but not *.o files : *.mod files of gfortran are not compatible with *.mod files of ifort. Therefore, when you build a library, you should put all your API functions and subroutines outside of the modules. For example:
don't do this:
module x
...
contains
subroutine sub_x
...
end subroutine sub_x
end module
but do this instead:
module x
...
end module
subroutine sub_x
use x
...
end subroutine sub_x
In this way you don't require the users to use mod files, and you can distribute your library as a .a or a .so archive.
In your case, the library you use was almost surely compiled with gfortran, so you are stuck with gfortran. The solution is to write another library as a wrapper around the original library. For example, do this
for each function/subroutine you need:
subroutine wrapped_sub_x(arguments)
use x
call sub_x(arguments)
end
Then, you compile your wrapper library with gfortran in a .a archive, and you link it to your project with ifort. In your project, don't forget to call your wrapper library instead of the original library.

Related

Linking problem when Calling/Including subroutines defined on separated files on Fortran using CMake

We have a quite large Fortran program that's developed and builded using Visual Studio and Ifort for Windows. On the linux side, we used to get the .dep generated on windows side, proccess it using a script, and create a command line call with the files on the order needed for the compilation. Now, I'm trying to rewrite the linux build using CMake.
After many solved problems (casing, enconding, ...) I've encountered some errors on the linking part. We have some subroutines defined on separated files that get called straight from other files like: CALL SUBROUTINE_NAME ()
I guess VisualStudio is somehow handling this linking but when I try to compile it using CMake on linux i get an error "undefined reference to SUBROUTINE_NAME".
My first tought was trying to include the file where this routine is defined but the subroutines are defined on multiple directories and, as far I understand, unless I put all this places on the include path for the compiler they can't be found.
Another option would be rewriting all this as modules and using them where needed. I guess this would be a cleaner solution but also a lot of work that I'm not sure I'd have the time for now.
First of all, I'd like to make sure my reasoning seems right and then what would be the best or some alternatives way to deal with this, like a way to manually include the paths for each occurrence or if there's a way to make CMake work like VisualStudio and resolve this references for example.
Thanks in advance for any insight and don't hesitate to get in touch and ask for more information if needed.
Edit to add more CMake info as requested:
CMakeLists.txt:
file(GLOB_RECURSE sources ./src/*.for)
add_executable(program_name ${sources}
target_include_directories(program_name PUBLIC "./src/includes")
I've managed to manually compile the file passing the .o of the separated subroutine but couldn't get CMake to include it as needed.
My subroutine file is been processed by CMake and a .o file is been generated for it, as I'm passing it as source.
Whenever I use a module, CMake can automatically add the module as a dependency for the file. But on this cases, where I'm calling the subroutine directly it doesn't generate the correct dependency for the Makefile.

CMake parallel build for Fortran-90+ with modules

I have a problem building multiple Fortran-90+ executable targets using CMake, when I use Fortran modules that are shared by all executables, and build in parallel using make -j. The issue seems to be that the compiled object files are placed in different subdirectories for each target, CMakeFiles/targetName.dir/src/file.f90.o, while the module files are placed in the same directory for every target (I can change this directory by setting Fortran_MODULE_DIRECTORY, but it will still be the same dir for all module files). The problem is then that all targets start writing these module files in parallel, and I get a
Fatal Error: Can't rename module file 'module.mod0' to 'module.mod': No such file or directory
when using gfortran (which apparently creates a .mod0 file and then renames it to .mod). The problem does not arise when I issue make without the -j option (serial build).
I can see two solutions, but I don't know how to implement them. Firstly, put the object files for all targets in the same directory rather than target-specific directories. This may be the preferred option, since I won't have to compile the shared source files N times for N targets. The make process will then recognise that the object files exist, and not compile the corresponding source files again, hence not touching the .mod(0) files again (I may need to make all following targets depend on the first).
The second solution would be to put the .mod(0) files in the target-specific directories, so that they are not overwritten or removed by the other targets. This would solve my problem, even though it would still involve more compiling than necessary. I have no idea how to accomplish either option, so any hint there or alternative solution is welcome.
The answer I was looking for was provided in the comments to the question by #RaulLaasner:
I would create an additional target in the form of a core library of the relevant source files, which can then be linked to all executables. This should work in parallel. The mod files can still be in put into a single directory.
I used add_library() and target_link_libraries() to achieve this.
Note that e.g. Gentoo ebuild scripts add --as-needed to the linker, which may cause undefined references in your core library when you link it and external libraries to form the executable. To prevent this, make sure you link the external libraries to your core library first. To this end, my CMakeListst.txt contains:
add_library( "Core" STATIC src/functions.f90 src/routines.f90 ) # creates libCore.a
target_link_libraries( Core ${EXTERNAL_LIBRARIES} ) # link external libraries to libCore.a
...
add_executable( myProgram1 src/myProgram1.f90 ) # creates the first executable
target_link_libraries( myProgram1 Core ) # links libCore.a to myProgram1
The last two lines can be repeated to build the other executables (e.g. using foreach()).

Compile Shared DLL in MinGW using Static Libraries

I am trying to create a single DLL for librsvg that does not require any other DLL and can be used within a MSVC application. Using MinGW/MSYS I have compiled librsvg (and its 20 dependencies) and produced a DLL but all libraries are shared and ultimately I need 21 DLLs. I have read and tried many dozens of articles and tried many different scenarios with the linker flag -static. I have used --enable-static on all the dependencies and produced the .a static libraries for each. However, I cannot seem to reach the end goal. When compiling librsvg I can either produce the DLL with shared libraries or I can produce a shared library for it w/o creating a DLL - I cannot reach the goal of a single DLL. I have also gone down the path of manually changing the makefile for librsvg and changing all the -l{library} lines to library.a and ultimately never got a clean compile due to issues with libtool. If this is the correct path I will continue; however, it seems the entire purpose of libtool is to accomplish this goal w/o the need to modify the makefile. Is there a better way? Is this even possible?

Adding a shared library and executable, compiling source files twice

gcc (GCC) 4.7.2
cmake version 2.8.11
Hello,
I wondering if there is a way around the following issue. I have highlighted below:
SET(GW_SOURCE_FILES
module.c
module_imp.c
module_message.c
module_config.c
module_queue.c)
# Compiles the source files to create the shared library called dlg_gw.so
ADD_LIBRARY(dlg_gw SHARED ${GW_SOURCE_FILES})
# Link additional libraries to this
TARGET_LINK_LIBRARIES(dlg_gw gc srl ${APRUTIL})
# ISSUE: Now I want to create my executable using the same source files. module.c is where my 'void main(void)' is.
# However, I have some functions in there which will also be part of the library.
# However, this will recompile the same source files all over again. I don't really like that behaviour.
ADD_EXECUTABLE(sun_gw ${GW_SOURCE_FILES})
# After the executable is created, link the libraries with it.
TARGET_LINK_LIBRARIES(sun_gw ${APR} driver dlg_gw dlg_sip dlg_ss7 dlg_isdn)
I hope you can see the issue above, as I am compiling the same source files twice. Once to create the dlg_gw library. Then again to create the executable sun_gw.
I was thinking of taking out the 'void main(void)' and putting it in a new file called runtime.c and then doing the following:
ADD_EXECUTABLE(sun_gw runtime.c)
But the above require me to change some of the source code.
Many thanks for any other suggestions,
The "OBJECT" library type introduced in CMake 2.8.8 can be used to avoid repetitive build of same files.
See http://www.cmake.org/Wiki/CMake/Tutorials/Object_Library

How do you use libtool to create .a files (static libraries) on Mac OS?

When it comes to using the terminal to build libraries manually and such I unfortunately do not have much experience and I'm stuck a bit here.
I've downloaded a library for objective-c which came with makefiles and such.
I can see that the folder also contains an executable file called "libtool", I did some searching and I suppose this is the program I have to use to build the neccessary .a files? Unfortunately I couldn't really find any useful article for this that seemed to work.
The folder for the library contains some .sh files, .pc files and also some .la files, but I'm a bit unsure of which ones I have to use as input to the libtool program to compile them into a .a file.
So my question is what files do you have to input into libtool to compile them into the necessary .a file? And what commands do you use exactly to accomplish this?
Thank you all for your time :)
First a little introduction to static libraries:
Static libraries in Unix environments (like Mac OSX, and Linux too) are actually just an archive of object files created by the ar command line program.
That is what the .a extension stands for: Archive.
To create a static library with some object files you can use the command like this:
ar crv libmy_library.a objectfile1.o objectfile2.o
As for your actual question, libtool should be called automatically from the makefile, creating the library, which is the file ending in .la. However, this is not the real library, the real library is in a hidden directory. You can find it by doing e.g.
find . -name '*.a'
But like I said, the makefile should already take care of everything, including installing the correct library in the correct place when you do e.g. make install.
For information about libtool, see this site.