Using CMake with ifort compiler - cmake

I am using CMake 2.8.7 on a Linux machine with Intel 11.0 compilers. I am trying to use CMake for the first time as I would like to build this project on both Windows and Linux machines.
I though of using a simple approach first and used a standard Hello World example:
My src/HelloWorld.f90:
!Test helloworld in Fortran using Cmake
program hello
print *, "Hello World!"
end program hello
My main CMakeLists.txt:
# States that CMake required version must be greater than 2.8.7
cmake_minimum_required(VERSION 2.8.7)
enable_language (Fortran)
project(helloworld Fortran)
add_subdirectory(src)
SET_TARGET_PROPERTIES(helloworld PROPERTIES LINKER_LANGUAGE FORTRAN)
My src/CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.7)
# Include the directory itself as a path to include directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# For a large number of source files you can create it in a simpler way
# using file() function:
file(GLOB helloworld_SOURCES *.f90)
I still get an error which says CMAKE_FORTRAN_LINK_EXECUTABLE variable missing. I looked at Abinader's CMake tutorial#1, but haven't had success so far.
any suggestions?? Thanks in advance !

Not a direct answer, as I've never used fortran with cmake, but I can see a few issues here.
First of all: where is your target helloworld defined? project is not a target.
Secondly: where do you use helloworld_SOURCES variable?
Try a more regular way. In your src/CMakeLists.txt add line at the end of file with:
add_executable(helloworld ${helloworld_SOURCES})
Also remove SET_TARGET_PROPERTIES(helloworld PROPERTIES LINKER_LANGUAGE FORTRAN) from main one as it should not be necessary.
Last advice: try not to use file(GLOB ). It is better to define list of all files manualy.

Probably the upper-case "FORTRAN", when setting the linker language is the problem. Try writing it as "Fortran" as in the enable_language statement. CMake derives the variables it uses from the language and this causes CMake to look for CMAKE_FORTRAN_LINK_EXECUTABLE instead of CMAKE_Fortran_LINK_EXECUTABLE.

As also mentioned by Michal, the add_executable has to be added to your CMakeLists.txt.
I tested your issue with the following CMake configurations files
main CMakeLists.txt:
# States that CMake required version must be greater than 2.8.7
cmake_minimum_required(VERSION 2.8.7)
enable_language (Fortran)
project(helloworld Fortran)
add_subdirectory(src)
src/CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.7)
add_executable(helloworld HelloWorld.f90)
under Linux for following versions:
ifort (IFORT) 16.0.0.20150815
cmake version 2.8.12.2
I prefer to use cmake-gui. There you can define the ifort compiler as follows:
After definition of source code and binary folder, e.g. build, press "Configure" and select
Click "Next" and define the following compilers
Click "Finish" and "Generate".
Go to build/src folder and execute make. The helloworld executable is generated with ifort successfully and could be called here.
Hint: If ifort is already the default native compiler on your Linux computer then you don't have to specify it in cmake-gui and can go ahead with the first option "Use default native compilers".
Hope it helps.

Let's try this step-by-step:
1) Your Fortran Hello, world is OK!
src/hello.f90
!Test helloworld in Fortran using Cmake
program hello
print *, "Hello World!"
end program hello
2) Now let's write the "inner" CMakeLists.txt
src/CMakeLists.txt
add_executable(helloworld hello.f90)
set_target_properties(
helloworld
PROPERTIES
LINKER_LANGUAGE Fortran
RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/build)
Here we've created an executable file, which you haven't in your question. Also, we've set its linker language to Fortran (it's case-sensitive parameter!) and the output directory for the compiled file.
3) Now we'll create the "main" CMakeLists.txt
CMakeLists.txt
# States that CMake required version must be greater than 2.8.7
cmake_minimum_required(VERSION 2.8.7)
project(helloworld Fortran)
add_subdirectory(src)
Here we've specified the src subdirectory with inner CMakeLists.txt and the compiler language - it's enough to use project() function, there's not need to use it together with enable_language().
4) Finally, let's build our code in out-of-source manner and run it!
cmake -S . -B build
cmake --build build
./build/helloworld

Related

CMake Project-level CXX override [duplicate]

This is similar to Force CMake to use C++ compiler for C files with Visual Studio, but its not quite the same. Its not the same because a its CMake file causing the failure; and I'm working on nearly every modern platform, from BSDs and OS X through Solaris and Unix.
I tried to avoid useless checks being performed by CMake:
project(cryptopp, CXX)
Here's what happens when I attempt to generate the makefile:
$ cmake .
-- Check if the system is big endian
-- Searching 16 bit integer
-- Check size of unsigned short
CMake Error at /usr/share/cmake-2.8/Modules/CheckTypeSize.cmake:82 (try_compile):
Unknown extension ".c" for file
/home/jeffrey/cryptopp/CMakeFiles/CheckTypeSize/CMAKE_SIZEOF_UNSIGNED_SHORT.c
try_compile() works only for enabled languages. Currently these are:
CXX
See project() command to enable other languages.
Call Stack (most recent call first):
/usr/share/cmake-2.8/Modules/CheckTypeSize.cmake:167 (__check_type_size_impl)
/usr/share/cmake-2.8/Modules/TestBigEndian.cmake:27 (CHECK_TYPE_SIZE)
CMakeLists.txt:49 (TEST_BIG_ENDIAN)
We don't have any C files in our project, so we should be safe with project(cryptopp, CXX) (if I am reading cmake --help-command project correctly).
The cited question talks about project files, but not CMake files.
How do I tell CMake to use C++ compiler for all files, including its own CMake files?
I'm on Ubuntu 12 LTS, and it provides:
$ cmake --version
cmake version 2.8.7
There are ways to add .c as a valid file extension for the CXX compiler. Even this being very advanced CMake stuff, you may need - if you are bound to support older versions of CMake - a "make rules overwrite script" anyway.
So I've successfully tested the following:
CryptoppMakeRulesOverwrite.cmake
list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS c)
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.7 FATAL_ERROR)
set(CMAKE_USER_MAKE_RULES_OVERRIDE "CryptoppMakeRulesOverwrite.cmake")
project(cryptopp CXX)
include(CheckTypeSize)
CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT)
As #Tsyvarev has commented check_type_size() supports a LANGUAGE parameter, but unfortunately not for CMake version 2.8.7. But this older version does already support CMAKE_USER_MAKE_RULES_OVERRIDE.
So I'm still wondering if not the best solution would be to go to a newer version of CMake (forcing some users of older CMake versions to upgrade). Or writing your own try_compile() snippets.
References
How to add in a CMake project a global file extension (*.pde) to GCC which is treated like C++ code
Change default value of CMAKE_CXX_FLAGS_DEBUG and friends in CMake
set_source_files_properties
The CMake setting of (my) choice here would be the set_source_files_properties command. https://cmake.org/cmake/help/latest/command/set_source_files_properties.html
set(qpid_dispatch_SOURCES
alloc.c
alloc_pool.c
aprintf.c
amqp.c
atomic.c
# [...]
)
set_source_files_properties(${qpid_dispatch_SOURCES} PROPERTIES LANGUAGE CXX)
add_library(qpid-dispatch OBJECT ${qpid_dispatch_SOURCES})
As described in the linked docs, CMake 3.18 changed the scoped effect of set_source_files_properties. See the DIRECTORY and TARGET_DIRECTORY options. Therefore, to apply source file property recursively to all files in your project, your CMakeLists.txt should look something like this
cmake_minimum_required(VERSION 3.20)
project(qpid-dispatch LANGUAGES C CXX)
# [...]
add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(router)
# [...]
file(GLOB_RECURSE CFILES "*.c")
set_source_files_properties(${CFILES}
DIRECTORY src tests router
PROPERTIES LANGUAGE CXX)
Copy the world
There is another approach that I've heard can be made to work: in your CMakeLists.txt, recursively copy all *.c files into *.cpp files and declare separate CMake targets to compile the copies. This has the advantage of allowing you to produce C-compiled and CXX-compiled artifacts at the same time, should you need anything like that.
Another braindead way of doing this (I just tried the set_source_files_properties() route and it just didn't even try to compile the files).
Rather than figure out the rats nest of cmake stuff I'm saddled with, I just added a C++ file that #includes the .c file, and added the C++ file to the CMakeLists.txt sources.
Braindead and stupid, but I'm having to deal with horrific code I'm importing. C header files without extern "C" in them, being used by C++ files.

Tell CMake to use C++ compiler for C files coming from CMake?

This is similar to Force CMake to use C++ compiler for C files with Visual Studio, but its not quite the same. Its not the same because a its CMake file causing the failure; and I'm working on nearly every modern platform, from BSDs and OS X through Solaris and Unix.
I tried to avoid useless checks being performed by CMake:
project(cryptopp, CXX)
Here's what happens when I attempt to generate the makefile:
$ cmake .
-- Check if the system is big endian
-- Searching 16 bit integer
-- Check size of unsigned short
CMake Error at /usr/share/cmake-2.8/Modules/CheckTypeSize.cmake:82 (try_compile):
Unknown extension ".c" for file
/home/jeffrey/cryptopp/CMakeFiles/CheckTypeSize/CMAKE_SIZEOF_UNSIGNED_SHORT.c
try_compile() works only for enabled languages. Currently these are:
CXX
See project() command to enable other languages.
Call Stack (most recent call first):
/usr/share/cmake-2.8/Modules/CheckTypeSize.cmake:167 (__check_type_size_impl)
/usr/share/cmake-2.8/Modules/TestBigEndian.cmake:27 (CHECK_TYPE_SIZE)
CMakeLists.txt:49 (TEST_BIG_ENDIAN)
We don't have any C files in our project, so we should be safe with project(cryptopp, CXX) (if I am reading cmake --help-command project correctly).
The cited question talks about project files, but not CMake files.
How do I tell CMake to use C++ compiler for all files, including its own CMake files?
I'm on Ubuntu 12 LTS, and it provides:
$ cmake --version
cmake version 2.8.7
There are ways to add .c as a valid file extension for the CXX compiler. Even this being very advanced CMake stuff, you may need - if you are bound to support older versions of CMake - a "make rules overwrite script" anyway.
So I've successfully tested the following:
CryptoppMakeRulesOverwrite.cmake
list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS c)
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.7 FATAL_ERROR)
set(CMAKE_USER_MAKE_RULES_OVERRIDE "CryptoppMakeRulesOverwrite.cmake")
project(cryptopp CXX)
include(CheckTypeSize)
CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT)
As #Tsyvarev has commented check_type_size() supports a LANGUAGE parameter, but unfortunately not for CMake version 2.8.7. But this older version does already support CMAKE_USER_MAKE_RULES_OVERRIDE.
So I'm still wondering if not the best solution would be to go to a newer version of CMake (forcing some users of older CMake versions to upgrade). Or writing your own try_compile() snippets.
References
How to add in a CMake project a global file extension (*.pde) to GCC which is treated like C++ code
Change default value of CMAKE_CXX_FLAGS_DEBUG and friends in CMake
set_source_files_properties
The CMake setting of (my) choice here would be the set_source_files_properties command. https://cmake.org/cmake/help/latest/command/set_source_files_properties.html
set(qpid_dispatch_SOURCES
alloc.c
alloc_pool.c
aprintf.c
amqp.c
atomic.c
# [...]
)
set_source_files_properties(${qpid_dispatch_SOURCES} PROPERTIES LANGUAGE CXX)
add_library(qpid-dispatch OBJECT ${qpid_dispatch_SOURCES})
As described in the linked docs, CMake 3.18 changed the scoped effect of set_source_files_properties. See the DIRECTORY and TARGET_DIRECTORY options. Therefore, to apply source file property recursively to all files in your project, your CMakeLists.txt should look something like this
cmake_minimum_required(VERSION 3.20)
project(qpid-dispatch LANGUAGES C CXX)
# [...]
add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(router)
# [...]
file(GLOB_RECURSE CFILES "*.c")
set_source_files_properties(${CFILES}
DIRECTORY src tests router
PROPERTIES LANGUAGE CXX)
Copy the world
There is another approach that I've heard can be made to work: in your CMakeLists.txt, recursively copy all *.c files into *.cpp files and declare separate CMake targets to compile the copies. This has the advantage of allowing you to produce C-compiled and CXX-compiled artifacts at the same time, should you need anything like that.
Another braindead way of doing this (I just tried the set_source_files_properties() route and it just didn't even try to compile the files).
Rather than figure out the rats nest of cmake stuff I'm saddled with, I just added a C++ file that #includes the .c file, and added the C++ file to the CMakeLists.txt sources.
Braindead and stupid, but I'm having to deal with horrific code I'm importing. C header files without extern "C" in them, being used by C++ files.

Getting a CMake Error: Cannot specify link libraries for target which is not built by the project

I am implementing CMake in my code but I'm getting the error
"Cannot specify link libraries for target "Qt5::Widgets" which is not built by the project".
Below are the contents of the CMakeLists.txt:
#Specify the version being used aswell as the language
cmake_minimum_required(VERSION 2.6)
#Name your project here
project(eCAD)
#Sends the -std=c++11 flag to the gcc compiler
ADD_DEFINITIONS(-std=c++11)
#This tells CMake to main.cpp and name it eCAD
add_executable(eCAD main.cpp)
#include the subdirectory containing our libs
add_subdirectory (gui)
include_directories(gui)
#include Qt directories
find_package(Qt5Widgets)
find_package(Qt5Core)
find_package(Qt5Designer)
SET(QT_USE_QTDESIGNER ON)
#link_libraries
target_link_libraries(Qt5::Widgets Qt5::Core)
In addition to the accepted answer: An important detail is to place target_link_libraries after the add_executable and find_package lines, so all linked components are known.
The first argument of target_link_libraries is the target name:
target_link_libraries(eCAD Qt5::Widgets Qt5::Core)
Also, do not confuse target name with the project name:
a command project specifies a project name, but
a target is the one created with add_executable, add_library or add_custom_target.
The error message is about the target.
Set you_lib_name before setting target_link_libraries
set(you_lib_name libname)
target_link_libraries(you_lib_name Qt5::Widgets Qt5::Core)

How do I tell CMake to link in a static library in the source directory?

I have a small project with a Makefile which I'm trying to convert to CMake, mostly just to get experience with CMake. For purposes of this example, the project contains a source file (C++, though I don't think the language is particularly relevant) and a static library file which I've copied from elsewhere. Assume for argument's sake that the source code to the library is unavailable; I only have the .a file and the corresponding header.
My handmade Makefile contains this build rule:
main: main.o libbingitup.a
g++ -o main main.o libbingitup.a
which works fine. How do I tell CMake to reproduce this? Not literally this exact makefile, of course, but something that includes an equivalent linking command. I've tried the obvious but naive ways, like
add_executable(main main.cpp libbingitup.a)
or
add_executable(main main.cpp)
target_link_libraries(main libbingitup.a)
as well as various things with link_directories(.) or add_library(bingitup STATIC IMPORTED) etc. but nothing so far that results in a successful linkage. What should I be doing?
Version details: CMake 2.8.7 on Linux (Kubuntu 12.04) with GCC 4.6.3
CMake favours passing the full path to link libraries, so assuming libbingitup.a is in ${CMAKE_SOURCE_DIR}, doing the following should succeed:
add_executable(main main.cpp)
target_link_libraries(main ${CMAKE_SOURCE_DIR}/libbingitup.a)
If you don't want to include the full path, you can do
add_executable(main main.cpp)
target_link_libraries(main bingitup)
bingitup is the same name you'd give a target if you create the static library in a CMake project:
add_library(bingitup STATIC bingitup.cpp)
CMake automatically adds the lib to the front and the .a at the end on Linux, and .lib at the end on Windows.
If the library is external, you might want to add the path to the library using
link_directories(/path/to/libraries/)
I found this helpful...
http://www.cmake.org/pipermail/cmake/2011-June/045222.html
From their example:
ADD_LIBRARY(boost_unit_test_framework STATIC IMPORTED)
SET_TARGET_PROPERTIES(boost_unit_test_framework PROPERTIES IMPORTED_LOCATION /usr/lib/libboost_unit_test_framework.a)
TARGET_LINK_LIBRARIES(mytarget A boost_unit_test_framework C)
I want to add to the other comments, the project name is the first argument. I had a project called cmakecompile and i wanted to add libusb to it, the code is as follows,
add_executable(cmakecompile main.c)
target_link_libraries(cmakecompile "D:/msys2/mingw64/lib/libusb-1.0.a")
the project had just only a main.c file, the first parameter in target_link_libraries is the name of your project and the second parameter is the path of the library.
Note that may help: Since i am compiling under windows, i had to install msys2 because the library you have has to be compiled with the same compiler. For example if you get libusb and try to use it in a qt-creator project, it will not work and you may get unreferenced functions, therefore i had to install msys2 and install libusb from inside msys2, install make and create a QT Cmake project and compile from Qt creator using the msys2 make.
The full cmakelists.txt is as follow
cmake_minimum_required(VERSION 3.5)
project(cmakecompile LANGUAGES C)
add_executable(cmakecompile main.c)
target_link_libraries(cmakecompile "D:/msys2/mingw64/lib/libusb-1.0.a")

CMake executable location

I have a very simple directory structure:
Project
Project/src
Project/build
Source files are in Project/src, and I do the out-of-src build in Project/build. After running cmake ../ ; make, I can run the executable thusly: Project/build$ src/Executable - that is, the Executable is created in the build/src directory.
How do I set the location of the executable in the CMakeLists.txt file? I've attempted to follow some of the examples found at cmake.org, but the links that work don't seem to show this behaviour.
My Project/src/CMakeLists.txt file is listed here.
include_directories(${SBSProject_SOURCE_DIR}/src)
link_directories(${SBSProject_BINARY_DIR}/src)
set ( SBSProject_SOURCES
main.cpp
)
add_executable( TIOBlobs ${SBSProject_SOURCES})
And the top-level Project/CMakeLists.txt:
cmake_minimum_required (VERSION 2.6)
project (SBSProject)
set (CMAKE_CXX_FLAGS "-g3 -Wall -O0")
add_subdirectory(src)
You have a couple of choices.
To change the default location of executables, set CMAKE_RUNTIME_OUTPUT_DIRECTORY to the desired location. For example, if you add
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
to your Project/CMakeLists.txt before the add_subdirectory command, your executable will end up in Project/build for Unix builds or build/<config type> for Win32 builds. For further details, run:
cmake --help-property RUNTIME_OUTPUT_DIRECTORY
Another option for a project of this size is to have just one CMakeLists.txt. You could more or less replace add_subdirectory(src) with the contents of Project/src/CMakeLists.txt to achieve the same output paths.
However, there are a couple of further issues.
You probably want to avoid using link_directories generally. For an explanation, run
cmake --help-command link_directories
Even if you do use link_directories, it's unlikely that any libraries will be found in ${SBSProject_BINARY_DIR}/src
Another issue is that the CMAKE_CXX_FLAGS apply to Unix builds, so should probably be wrapped in an if (UNIX) ... endif() block. Of course, if you're not planning on building on anything other than Unix, this is a non-issue.
Finally, I'd recommend requiring CMake 2.8 as a minimum unless you have to use 2.6 - CMake is an actively-developed project and the current version has many significant improvements over 2.6
So a single replacement for Project/CMakeLists.txt could look like:
cmake_minimum_required (VERSION 2.8)
project (SBSProject)
if (UNIX)
set (CMAKE_CXX_FLAGS "-g3 -Wall -O0")
endif ()
include_directories (${SBSProject_SOURCE_DIR}/src)
set (SBSProject_SOURCES
${SBSProject_SOURCE_DIR}/src/main.cpp
)
add_executable (TIOBlobs ${SBSProject_SOURCES})
Another way of relocating the executable file location is via set(EXECUTABLE_OUTPUT_PATH Dir_where_executable_program_is_located)
build/'config type' for Win32 builds.
For MSVC, to avoid the default "/Debug" created folder
set_target_properties(my_target
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR})