Cross Compiling problems with nestled CMakelists.txt files - cmake

I do need to include "Cross Compiling" in my project (Intel and PowerPC) and I have found a problem defining targets. I have the following folder structure:
libs
*.h
*.cpp
CMakeLists.txt
src
*.h
*.cpp
CMakeLists.txt
...
-CMakeLists.txt
If a write the following piece of code in the CMakeLists.txt of the src folder, It works ...
ADD_EXECUTABLE( intel ${SOURCES} ) SET_TARGET_PROPERTIES( intel PROPERTIES OUTPUT_NAME ${APP_NAME}_INTEL EXCLUDE_FROM_ALL true ) TARGET_LINK_LIBRARIES( intel ${LIBS_INTEL} )
However I don't really know how to do it in the CMakeLists of the libraries (libs folder). If I follow the same structure and use "intel" as a target, it returns an error message saying that "the target name is already used".
I do want to compile all my project with both options:
"make intel" --> to generate Intel version and "make powerPc" --> to generate PowerPC version
I have been looking for it on the Internet but I couldn't find a correct solution.
I hope anyone could help me.

Finally I found the solution. It was as easy as using the following macro in the main CMakeLists.txt file.
ADD_CUSTOM_TARGET ( INTEL DEPENDS EXECUTABLE1 EXECUTABLE2 ... EXECUTABLEN)
And the same with the other target powerpc.

Related

Issue finding and linking Psapi library to executable using cmake

I am trying to link the psapi library to a project with cmake, nothing complex. Here's my cmake-file:
cmake_minimum_required(VERSION 2.8)
project(BenchmarkTests)
add_definitions(-DPSAPI_VERSION=1)
if (WIN32)
FILE(GLOB win32_head
Timer.h
win_Memory.h
win_Processor.h
BenchmarkTests.h)
FILE(GLOB win32_source *.cpp)
SET(win32_test ${win32_head} ${win32_source})
SET(LIBDIR_NAME "C:/Program Files (x86)/Windows Kits/8.1/Lib/winv6.3/um/x64/")
SET(LIBDIR $ENV{${LIBDIR_NAME}})
SET(LIBNAME "Psapi.Lib")
find_library (Psapi ${LIBNAME} {LIBDIR})
ADD_EXECUTABLE(bmTests ${win32_test})
TARGET_LINK_LIBRARIES(bmTests Psapi)
SOURCE_GROUP("win32" FILES ${win32_test})
endif()
There are no other "Psapi.Lib" files on my computer except for in ".../um/x86", but my system is 64-bit so I want the x64, no? Anyhow the output in CMake GUI for Psapi field is "Psapi-NOTFOUND" and in VS2013 all of the functions in Psapi.h recieve syntax errors. I guess since they can't link to the library. Am I forgetting something vital in my cmake file? Any suggested fix or alternative method is welcome, thanks in advance.
I get the same result when I try the below instead of find_library(...)
add_library(Psapi STATIC IMPORTED)
set_property(TARGET Psapi PROPERTY IMPORTED_LOCATION "C:/Program Files (x86)/Windows Kits/8.1/Lib/winv6.3/um/x64/Psapi.Lib")
For future reference I got it to work in CMake as follows, credit goes to Chibueze Opata on this question:
find_library (PSAPI Psapi)
...
add_executable(...)
...
target_link_libraries(Basic -lpsapi)

How do I configure cmake to link to prebuilt shared libraries?

I have a project that includes a prebuilt version of opencv in a subdirectory. For example:
MyProject
* CMakeLists.txt
* src
* third_party
** CMakeLists.txt
** opencv
**** include
**** lib
I would like to link against the version of opencv located in the third_party directory. My question is, how do I inform CMake to link to the prebuilt dylib files in lib, and include the headers in the relevant opencv directory?
cmake_minimum_required(VERSION 2.8.9)
project (myproject)
include_directories(${CMAKE_SOURCE_DIR}/third_party/opencv/include)
link_directories(${CMAKE_SOURCE_DIR}/third_party/opencv/lib)
file(GLOB SOURCES "*.cpp")
add_executable(myproject ${SOURCES})
target_link_libraries(myproject opencv_calib3d opencv_contrib opencv_core opencv_highgui opencv_features2d opencv_highgui opencv_imgproc)
I've given your example a try with CMake 3.3.2 on OS X 10.11 having XCode 7.0.1.
Using the link_directories() and target_link_libraries() approach suggested by #Tsyvarev seems to work without raising any linker warnings or errors (it finds the .dylib libraries I placed in the third_party directory).
Just a view hints, that hopefully could get you a start why it's not working on your Mac.
With your code I get the following command line linker file (inside CMake's binary output directory):
CMakeFiles/myproject.dir/src/link.txt
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk
-Wl,-search_paths_first
-Wl,-headerpad_max_install_names
CMakeFiles/myproject.dir/src/main.cpp.o -o myproject
-L[...CMAKE_SOURCE_DIR...]/third_party/opencv/lib
-lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_highgui -lopencv_features2d -lopencv_highgui -lopencv_imgproc -lopencv_features2d -lopencv_imgproc
-Wl,-rpath,[...CMAKE_SOURCE_DIR...]/third_party/opencv/lib
You can try to give full library paths, because those are additionally checked by CMake itself and it gets more obvious what I link against. Here is a modified version of your example:
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.9)
project (myproject)
include_directories(${CMAKE_SOURCE_DIR}/third_party/opencv/include)
file(GLOB SOURCES "src/*.cpp")
file(GLOB LIBRARIES "third_party/opencv/lib/*.dylib")
message("LIBRARIES = ${LIBRARIES}")
add_executable(myproject ${SOURCES})
target_link_libraries(myproject ${LIBRARIES})
With this CMake just adds fully qualified paths (relative to my binary output directory) into the linker file. The -L and -l options are gone and you get "lines" like:
../third_party/opencv/lib/libopencv_calib3d.dylib
Additional Q/A References
OpenCV installation on Mac OS X
How to use dylib file in application?
CMake link_directories from library
Force CMake to use the full library path

CMake execution order - first build shared library then look for it from another project

I have the following cmake setup:
colorizer_root
|
|-------colorizer_lib
|-------colorizer_template_project
The colorizer_root contains the top level CMakeLists.txt which is invoked when running cmake:
colorizer_root CMakeLists.txt
project(colorizer_root)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_BUILD_TYPE Debug)
add_subdirectory(colorizer_lib)
add_subdirectory(colorizer_template_project)
As you can see it contains 2 subdirectories each a project on its own. Basically what the colorizer_lib does is create a shared library named libcolorize.so (no executables here!), which then is to be used by the other project colorizer_template_project (the executable is created in this project). Here are the two CMakeLists.txt files for their respective projects:
colorizer_lib CMakeLists.txt
project(colorizer_lib)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "--std=gnu++11 ${CMAKE_CXX_FLAGS}")
include_directories(. INCLUDES)
add_library(colorizer SHARED colorizer.cpp)
colorizer_template_project CMakeLists.txt
project(colorizer_template_project)
cmake_minimum_required(VERSION 2.8)
find_library(COLORIZER_LIB colorizer
PATHS ${CMAKE_BINARY_DIR}/colorizer_lib
)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} ${COLORIZER_LIB})
I'm having trouble figuring out how the whole lookup thing works. The problem here is that when I run the top level CMakeLists.txt it goes through both (obviously) but during processing the colorizer_template_project it breaks with a complaint:
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
COLORIZER_LIB
linked by target "colorizer_template_project" in directory /home/USER/Programming/C_Cpp/colorizer/colorizer_template_project
This is an expected behaviour since libcolorizer.so cannot be present at the time of running cmake because it is created after make has been invoked.
How do I tell cmake to first process the first project (including the build step!) and then go to the next one? I know that this works if I add an executable to the project that creates the library and then directly link it to the binary but in this case I want separate projects for the library and the executable that is using it.
PS: I haven't given any details about the sources because they are not important here. It is - I believe - a general question, which is not specific to whether I'm using C, C++ or something similar.
project command doesn't make subprojects independent, so colorizer target is actually accessible for colorizer_template_project, and you can directly link with it:
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} colorizer)

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")

Using CMake with ifort compiler

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