I'm a robotics' student from Instituto Superior Técnico and I'm having trouble using an external library in my project.
I use a Robotics simulator called Simox http://simox.sourceforge.net/. This is a library that I have been working for a while. I have been using a cmake template file provided with the simulator (with few alterations) which lets me use Simox with my own code:
PROJECT ( myDemo )
FIND_PACKAGE(Simox REQUIRED)
IF(Simox_USE_COIN_VISUALIZATION)
include_directories(${PROJECT_SOURCE_DIR}/include)
FILE(GLOB SRCS ${PROJECT_SOURCE_DIR}/iCubSimulator.cpp ${PROJECT_SOURCE_DIR}/src/iCub.cpp ${PROJECT_SOURCE_DIR}/src/iCubHand.cpp ${PROJECT_SOURCE_DIR}/src/ApproachMovementSpace.cpp ${PROJECT_SOURCE_DIR}/src/OrientedBoundingBox.cpp ${PROJECT_SOURCE_DIR}/src/GraspOptimization.cpp ${PROJECT_SOURCE_DIR}/src/Window.cpp)
FILE(GLOB INCS ${PROJECT_SOURCE_DIR}/include/iCub.h ${PROJECT_SOURCE_DIR}/include/iCubHand.h ${PROJECT_SOURCE_DIR}/include/ApproachMovementSpace.h ${PROJECT_SOURCE_DIR}/include/OrientedBoundingBox.h ${PROJECT_SOURCE_DIR}/include/Window.h)
set(GUI_MOC_HDRS ${PROJECT_SOURCE_DIR}/include/GraspOptimization.h ${PROJECT_SOURCE_DIR}/include/Window.h)
set(GUI_UIS ${PROJECT_SOURCE_DIR}/ui/iCubSimulator.ui)
set(CMAKE_CXX_FLAGS "-Wall -std=c++11 -lpthread")
SimoxQtApplication(${PROJECT_NAME} "${SRCS}" "${INCS}" "${GUI_MOC_HDRS}" "${GUI_UIS}")
ENDIF()
Currently, I want to use an additional Bayesian Optimization Library called BayesOpt: http://rmcantin.bitbucket.org/html/. And I don't know how to correctly modify my cmake file to include this library.
I tried to do this own my own, with some help from google, tutorials and other asked questions, but with no success.
I'm hoping someone can help me with this problem.
Thanks in advance!
To use an external library, you will need to:
Make header files from the library accessible:
INCLUDE_DIRECTORIES( includePath )
includePath being your Bayesian Optimization Library include folder (where .h files are)
Link with the library. To do so, just add:
TARGET_LINK_LIBRARIES(${PROJECT_NAME} mylib)
myLib being your Bayesian Optimization Library .lib file or .so file
Maybe you'll first have to compile the "Bayesian Optimization Library"
If the library is correctly installed in your environment, there could be an easier way to have it be found using CMake find_package command, but I'm not familiar with it, I prefer to handle things manually as proposed aboce.
Related
I am new to cmake and know this question has been asked before, but still cannot find what I am doing wrong. I have an external library with folders /include and lib. The /include folder contains all the headers (.h) and the /lib folder contains all the source (.c) files.
In my project I have this CMakeList.txt file:
cmake_minimum_required(VERSION 3.7)
project(FirstAttempt)
set(CMAKE_CXX_STANDARD 11)
set (EXTRA_LIBS "D:\\libtrading")
include_directories(${EXTRA_LIBS}/include)
link_directories(${EXTRA_LIBS}/include)
set(SOURCE_FILES main.cpp)
add_executable(FirstAttempt ${SOURCE_FILES})
target_link_libraries (FirstAttempt ${EXTRA_LIBS}/lib)
I know that I have to use target_link_libraries to link the source files of the library to my project, but certainly something is missing, but what? I am still receiving the error undefined reference to xxxxxx.
The library I am trying to include in my project is https://github.com/libtrading/libtrading.
Well, I'll try.
First, seems that you are calling link_directories() on the folder which contains header files, while it should be used in order to specify the path where to search libraries for.
Second, target_link_libraries() takes the absolute path of the shared/static library file as the second argument, while you are passing the directory path (well, it seems so).
target_link_libraries() doesn't link to the "source files of the library", - it links to the compiled shared/static library blob.
And, I would also recommend you to save the name of the executable to the variable so that you wouldn't be able to mistype the target name, like so:
set(TARGET FirstAttempt)
add_executable(${TARGET})
As you know, we need all source files to compile. So we need to point out Cmake know where/what are source files.
I think you should add all sources files like this
file(GLOB SOURCES_FILES "lib/*.c" main.cpp)
to add all .c files.
Or, you can add all lib/*.c files separately
file(SOURCES_FILES_LIBS "lib/*.c")
set(SOURCES_FILES main.cpp)
add_executable(FirstAttempt ${SOURCES_FILES_LIBS} ${SOURCES_FILES})
I'm attempting to run a cmake hello world program on Windows 7 x64 with both Visual Studio 2010 and Cygwin, but can't seem to get either to work. My directory structure is as follows:
HelloWorld
-- CMakeLists.txt
-- src/
-- -- CMakeLists.txt
-- -- main.cpp
-- build/
I do a cd build followed by a cmake .., and get an error stating that
CMake Error: CMake can not determine linker language for target:helloworld
CMake Error: Cannot determine link language for target "helloworld".
However, if I change the extension of main.cpp to main.c both on my filsystem and in src/CMakeLists.txt everything works as expected. This is the case running from both the Visual Studio Command Prompt (Visual Studio Solution Generator) and the Cygwin Terminal (Unix Makefiles Generator).
Any idea why this code wouldn't work?
CMakeLists.txt
PROJECT(HelloWorld C)
cmake_minimum_required(VERSION 2.8)
# include the cmake modules directory
set(CMAKE_MODULE_PATH ${HelloWorld_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
add_subdirectory(src)
src/CMakeLists.txt
# Include the directory itself as a path to include directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Create a variable called helloworld_SOURCES containing all .cpp files:
set(HelloWorld_SOURCES main.cpp)
# Create an executable file called helloworld from sources:
add_executable(hello ${HelloWorld_SOURCES })
src/main.cpp
int main()
{
return 0;
}
I also got the error you mention:
CMake Error: CMake can not determine linker language for target:helloworld
CMake Error: Cannot determine link language for target "helloworld".
In my case this was due to having C++ files with the .cc extension.
If CMake is unable to determine the language of the code correctly you can use the following:
set_target_properties(hello PROPERTIES LINKER_LANGUAGE CXX)
The accepted answer that suggests appending the language to the project() statement simply adds more strict checking for what language is used (according to the documentation), but it wasn't helpful to me:
Optionally you can specify which languages your project supports.
Example languages are CXX (i.e. C++), C, Fortran, etc. By default C
and CXX are enabled. E.g. if you do not have a C++ compiler, you can
disable the check for it by explicitly listing the languages you want
to support, e.g. C. By using the special language "NONE" all checks
for any language can be disabled. If a variable exists called
CMAKE_PROJECT__INCLUDE_FILE, the file pointed to by that
variable will be included as the last step of the project command.
In my case, it was just because there were no source file in the target. All of my code was a template with the source code in the header file. Adding an empty file.cpp solved the problem.
Try changing
PROJECT(HelloWorld C)
into
PROJECT(HelloWorld C CXX)
or just
PROJECT(HelloWorld)
See: https://cmake.org/cmake/help/latest/command/project.html
Confusing as it might be, the error also happens when a cpp file included in the project does not exist.
If you list your source files in CMakeLists.txt and mistakenly type a file name then you get this error.
I want to add another solution in case a library without any source files shall be build. Such libraries are also known as header only libraries. By default add_library expects at least one source file added or otherwise the mentioned error occurs. Since header only libraries are quite common, cmake has the INTERFACE keyword to build such libraries. The INTERFACE keyword is used as shown below and it eliminates the need for empty source files added to the library.
add_library(myLibrary INTERFACE)
target_include_directories(myLibrary INTERFACE {CMAKE_CURRENT_SOURCE_DIR})
The example above would build a header only library including all header files in the same directory as the CMakeLists.txt. Replace {CMAKE_CURRENT_SOURCE_DIR} with a path in case your header files are in a different directory than the CMakeLists.txt file.
Have a look at this blog post or the cmake documentation for further info regarding header only libraries and cmake.
A bit unrelated answer to OP but for people like me with a somewhat similar problem.
Use Case: Ubuntu (C, Clion, Auto-completion):
I had the same error,
CMake Error: Cannot determine link language for target "hello".
set_target_properties(hello PROPERTIES LINKER_LANGUAGE C) help fixes that problem but the headers aren't included to the project and the autocompletion wont work.
This is what i had
cmake_minimum_required(VERSION 3.5)
project(hello)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES ./)
add_executable(hello ${SOURCE_FILES})
set_target_properties(hello PROPERTIES LINKER_LANGUAGE C)
No errors but not what i needed, i realized including a single file as source will get me autocompletion as well as it will set the linker to C.
cmake_minimum_required(VERSION 3.5)
project(hello)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES ./1_helloworld.c)
add_executable(hello ${SOURCE_FILES})
I also faced a similar error while compiling my C-based code. I fixed the issue by correcting the source file path in my cmake file. Please check the source file path of each source file mentioned in your cmake file. This might help you too.
Simply check the path to source file. (to the respective cpp)
By default the JNI Native folder is named as jni . Renaming it to cpp fixed the issue
I managed to solve mine, by changing
add_executable(file1.cpp)
to
add_executable(ProjectName file1.cpp)
I have a header-only library project set up with the cmake command:
add_library(my_library INTERFACE)
and I also added
target_sources(my_library INTERFACE ${MY_LIRBARY_HEADER_FILES})
but when I open a source file, I get the warning:
This file does not belong to any project target, code insight features might not work properly
and I lose a lot of the functionality on things like code completion.
What is the proper way to set this up so CLion provides its usual functionality on a header-only library?
Little background
I was having the same problem, albeit the project was not header-only, nevertheless, the open files from inc folder were throwing the aforementioned warning, even though the CMake file clearly marked that folder to be include_directory.
*.hpp files do not belong to ${SOURCE}
include_directories("${PROJECT_SOURCE_DIR}/inc/")
add_subdirectory(src)
add_executable(${EXECUTABLE_NAME} main.cpp ${SOURCE})
Since this is a perfectly valid CMake file and adding the include files to source files is not idiomatic, I did not want to amend the CMake file.
The solution
As described on the official JetBrains Forum, the CMake file is indeed valid and the warning is shown because of the inability of CLion to properly index header files. The suggested workaround extracted from the link is to right-click the folder and Mark directory as | Library Files/Project Sources and Headers.
So, this header isn't includes in executables and CLion notifies you that some code insight features might not work properly. As workaround you can use "Mark directory as" Library Files/Project Source and Headers for folder.
Clion takes information about source files from CMake build system. When you add any cpp file to sources list CMake automatically tell about header with same name. So if cpp/h names differs (or you don't have cpp file at all) you should include header manually.
set(Sources my_lib.cpp)
set(Headers header_of_my_lib.h)
add_executable(superlib ${Sources} ${Headers})
If you don't have any executable you can omit last line, CLion will still know about files
This warning is an IDE issue that Android Studio cannot recognise the current directory if it does not include any source files.
Workaround
Adding am empty source file, e.g empty_xxx.c under the directory in question and adding below line in your corresponding CMakeList.txt
add_library(${TARGET_NAME_XXX} SHARED ${SOME_DIR_HAVING_THIS_WARNING}/empty_xxx.c)
will help get rid of this warning.
You can add the header files to your project like this:
set(SOURCE_FILES main.cpp MyClass1.cpp MyClass1.h MyClass2.cpp MyClass2.h)
You can also set it in multiple steps like so:
set(SOURCE_FILES main.cpp)
set(SOURCE_FILES ${SOURCE_FILES} MyClass1.cpp MyClass1.h)
set(SOURCE_FILES ${SOURCE_FILES} MyClass2.cpp MyClass2.h)
Though as mentioned in the comments, you probably shouldn't be adding the header files to your project at all.
I am new to cmake and know this question has been asked before, but still cannot find what I am doing wrong. I have an external library with folders /include and lib. The /include folder contains all the headers (.h) and the /lib folder contains all the source (.c) files.
In my project I have this CMakeList.txt file:
cmake_minimum_required(VERSION 3.7)
project(FirstAttempt)
set(CMAKE_CXX_STANDARD 11)
set (EXTRA_LIBS "D:\\libtrading")
include_directories(${EXTRA_LIBS}/include)
link_directories(${EXTRA_LIBS}/include)
set(SOURCE_FILES main.cpp)
add_executable(FirstAttempt ${SOURCE_FILES})
target_link_libraries (FirstAttempt ${EXTRA_LIBS}/lib)
I know that I have to use target_link_libraries to link the source files of the library to my project, but certainly something is missing, but what? I am still receiving the error undefined reference to xxxxxx.
The library I am trying to include in my project is https://github.com/libtrading/libtrading.
Well, I'll try.
First, seems that you are calling link_directories() on the folder which contains header files, while it should be used in order to specify the path where to search libraries for.
Second, target_link_libraries() takes the absolute path of the shared/static library file as the second argument, while you are passing the directory path (well, it seems so).
target_link_libraries() doesn't link to the "source files of the library", - it links to the compiled shared/static library blob.
And, I would also recommend you to save the name of the executable to the variable so that you wouldn't be able to mistype the target name, like so:
set(TARGET FirstAttempt)
add_executable(${TARGET})
As you know, we need all source files to compile. So we need to point out Cmake know where/what are source files.
I think you should add all sources files like this
file(GLOB SOURCES_FILES "lib/*.c" main.cpp)
to add all .c files.
Or, you can add all lib/*.c files separately
file(SOURCES_FILES_LIBS "lib/*.c")
set(SOURCES_FILES main.cpp)
add_executable(FirstAttempt ${SOURCES_FILES_LIBS} ${SOURCES_FILES})
I'm trying to migrate from Visual Studio towards Jetbrains' (awesome) CLion IDE which uses CMake to organize the projects.
Until now, the transition has been smooth: creating CMake projects and importing them into CLion is easy, and I can begin coding on one plateform then continue on another one without problems.
However, one aspect of Visual Studio that I couldn't find an equivalent to in CMake is property sheets: I use them mainly for holding the include directories' paths and the linking libs for libraries (i.e. one .vsprops file for each library, e.g. OpenCV.vsprops, Boost.vsprops, etc.).
This way, in VS, I could share a library's .vsprops file between different projects without having to configure the paths/libs each time.
Does CMake have a similar mechanism to Visual Studio's property sheets ? How is it possible to store a library's includes/libs in a CMake-parsable file then "import" it in CMakeLists.txt in order to link against the library ?
Basically, what I want to do is:
Create a "cmake property sheet" (for lack of a better name) for a given library.
Then, in CMakeLists.txt, write something like link_target_to_libs(myTarget "path/to/propertySheet1" "path/to/propertySheet2" ...) .
In CMake, libraries can export a package with IMPORTED targets which other buildsystems import using find_package:
http://www.cmake.org/cmake/help/v3.1/manual/cmake-packages.7.html
http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html
http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#imported-targets
Instead of 'linking to property sheets', you link to the IMPORTED targets.
target_link_libraries(myTarget Dep1::Dep1 Dep2::Dep2)
Not all libraries create IMPORTED targets, and not all provide cmake config-file packages. In those cases (including OpenCV and Boost), CMake provides find modules:
http://www.cmake.org/cmake/help/v3.0/manual/cmake-developer.7.html#find-modules
which you use with find_package and link to the contents of variables.
Since I really want to make the libraries' inclusion/linking into a one-line command, and as far as my (basic) knowledge of CMake goes, I think that some compromise should be made -- mainly sharing the target name's variable between CMakeLists.txt and the "property sheets". So this is my solution... until someone proposes a simpler/cleaner one:
A CMake property sheet is a .cmake text file,
A well-known variable name --TARGET-- designates the target (i.e. the first argument of add_executable()),
Aside from library-specific commands, a .cmake file contains a call to target_include_directories(${TARGET} PRIVATE ${PATH_TO_INCLUDE_DIR}) and target_link_libraries(${TARGET} ${LIST_OF_LIBS}),
In order to use/link against a library, call include("path/to/.cmake") in CMakeLists.txt.
I have successfully built and executed a simple program that uses X11 and OpenCV with the following files:
x11.cmake
target_include_directories(${TARGET} PRIVATE "/usr/include/X11")
target_link_libraries(${TARGET} "/usr/lib/x86_64-linux-gnu/libX11.so")
opencv.cmake
# OpenCV-specific stuff
set(OpenCV_DIR "/PATH/TO/OPENCV/INSTALL/DIR/share/OpenCV") # path to OpenCVConfig.cmake
find_package(OpenCV REQUIRED)
# include path
target_include_directories(${TARGET} PRIVATE ${OpenCV_INCLUDE_DIRS})
# linking libs
target_link_libraries(${TARGET} opencv_world opencv_ts)
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.4)
project(hello_clion)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
## hello-clion ##############################
# make a new target name
set(TARGET hello-clion)
# find sources
file(GLOB_RECURSE SOURCE_FILES "src/*.cpp" "src/*.hpp")
# declare a target
add_executable(${TARGET} ${SOURCE_FILES})
# link the libraries (to the last-declared ${TARGET}, which should be the last-added executable)
include("x11.cmake")
include("opencv.cmake")
#############################################
main.cpp
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <thread>
#include <opencv2/opencv.hpp>
#include <Xlib.h>
int main_x11()
{
// adapted from: http://rosettacode.org/wiki/Window_creation/X11#Xlib
}
int main_ocv()
{
// adapted from: http://docs.opencv.org/doc/tutorials/introduction/display_image/display_image.html#source-code
}
int main()
{
using namespace std;
thread tocv(main_ocv);
thread tx11(main_x11);
tocv.join();
tx11.join();
return 0;
}
Now, each time I want to use OpenCV in a project/program, I just have to put include("opencv.cmake") in the corresponding CMakeLists.txt.
This seems to work great, but there could certainly be problems I haven't discovered. (I was worried multiple macros adding the same target_link_libraries would cause "already defined" linking errors , but at least g++ 5.1.0 handles being given the same library name multiple times without error.)
In root CMakeLists.txt, BEFORE add_subdirectory() calls or globs, include:
macro(USES_WX)
include_directories(SYSTEM /usr/local/include/wx-3.0)
include_directories(SYSTEM /usr/local/lib/wx/include/gtk3-unicode-3.0)
link_directories(/usr/local/lib)
add_definitions(-D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread)
target_link_libraries(${TARGET} pthread wx_gtk3u_xrc-3.0 wx_gtk3u_html-3.0 wx_gtk3u_qa-3.0 wx_gtk3u_adv-3.0 wx_gtk3u_core-3.0 wx_baseu_xml-3.0 wx_baseu_net-3.0 wx_baseu-3.0)
endmacro()
(You can make the macro more fancy, like checking for if CMAKE_BUILD_TYPE is "Debug" or "Release" to link to the appropriate libraries, vary preprocessor definitions, etc. See http://www.cmake.org/cmake/help/v3.0/command/if.html)
And have your project's CMakeLists.txt be like this:
set(TARGET myProgramName)
add_executable(${TARGET} myProgramName.cpp)
USES_WX()
^^ The macro call MUST be after add_executable()
And, if you want multiple target support, modify the line in the root CMakeLists.txt section shown above to:
...
target_link_libraries(${ARGV0} pthread wx_gtk3u_xrc-3.0 ...)
...
And have your project's CMakeLists.txt be like this (less lines, but more chance for error):
add_executable(myProgramName myProgramName.cpp)
USES_WX(myProgramName)