CMake having multiple executables throws me an error - cmake

I'm having some trouble with cmake: I'm using cmake for my school project and there is a bonus part but we have to compile another executable for the bonus part, and I tried this:
cmake_minimum_required(VERSION 3.10)
project(philosophers)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_COMPILER /usr/bin/clang)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "-Wall -Wextra -Werror")
set(CMAKE_EXE_LINKER_FLAGS "-lpthread")
set(LIBFT ${CMAKE_CURRENT_SOURCE_DIR}/lib/libft42/libft.a)
add_custom_command(OUTPUT ${LIBFT}
COMMAND make
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib/libft42)
link_libraries(philo_bonus ${LIBFT})
link_libraries(philo ${LIBFT})
aux_source_directory(src SRC)
aux_source_directory(src_bonus SRC_BONUS)
add_executable(philo ${SRC} ${LIBFT})
add_executable(philo_bonus ${SRC_BONUS} ${LIBFT})
target_include_directories(philo
PUBLIC inc
PUBLIC lib/libft42/inc)
target_include_directories(philo_bonus
PUBLIC inc_bonus
PUBLIC lib/libft42/inc)
I removed include_directories and replaced it with target_include_directories because I want my two projects to have separate includes, but when I try to cmake -Bbuild -H., it says:
CMake Error at CMakeLists.txt:23 (add_executable):
Target "philo_bonus" links to itself.
CMake Error at CMakeLists.txt:22 (add_executable):
Target "philo" links to itself.
CMake Error: Cannot determine link language for target "philo_bonus".
CMake Error: CMake can not determine linker language for target: philo_bonus
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
I don't understand what happened here, I changed nothing in add_executable and it worked fine before I added another.

Related

How to create CMakeLists for this make file [duplicate]

Work on Ubuntu 16
I used g++ main.cpp -lpq command for compiler my small project. Now I use Clion and wanna do same what I do with g++. But I can't add compiler flags in cmake file and get compile error.
cmake_minimum_required(VERSION 3.5.1)
project(day_g)
set(CMAKE_CXX_FLAGS "-lpq")
add_definitions(-lpq)
message("CMAKE_CXX_FLAGS is ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(day_g ${SOURCE_FILES})
Also I run only cmake file and get CMAKE_CXX_FLAGS with -lpq flag.
CMAKE_CXX_FLAGS is -lpq
-- Configuring done
-- Generating done
How properly add compiler flags to cmake file?
Flag -l is for linker, not for compiler. This flag is used for link with libraries. CMake has special command target_link_libraries for that purpose:
target_link_libraries(day_g pq)
-lq is not a compiler flag (CFLAGS) but a linker flag.
To pass a library in a CMake project you should use:
target_link_libraries(target_name libraries...)
Note that if you specify 'q' as library the project will link with libq.a or, if you are on windows q.dll.
... in your CMakeLists.txt the correct line to add is:
target_link_libraries(day_g pq)
Note also that when you add a CFLAG you should also "remember" the previous ones that may be added by libraries or by your platform, ie:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
To check the exact flags cmake is passing to compiler or linker you can always run, from the build directory, the following command:
make VERBOSE=1

how do i specify libraries's path to cmake which are used by target_link_libraries

I have some codebase which has cmake build system .while building iam getting an error as below
/usr/bin/ld: cannot find -lcurl
below is the sample cmakelist.txt
cmake_minimum_required(VERSION 2.8.6)
project(oci_object_test)
set(IB_HOME /home/user/sample_cmake/usr/lib)
include_directories(${LIB_HOME}/include)
link_directories(${LIB_HOME}/lib64)
link_directories(/home/user/sample_cmake/usr/lib/lib64)
link_directories(/home/user/)
set(SOURCES
sample.cpp
)
add_executable(demo ${SOURCES})
target_link_libraries(demo curl openssl)
for the above cmakelist.txt below is the link.txt generated by cmake
/usr/bin/c++ CMakeFiles/demo.dir/sample.cpp.o -o demo -L/home/user/sample_cmake/usr/lib/lib64 -L/home/user -rdynamic -lcurl -lopenssl -Wl,-rpath,/home/user/sample_cmake/usr/lib/lib64:/home/user
this issue is due to -lcurl getting added in link.txt generated by cmake . if i remove -lcurl from link.txt manually and build ,build will get success with no linker error . So is there any way i can get rid off this -lcurl in link.txt or is it possible to define -lcurl path where it actual libcurl present ( for example suppose libcurl present inside /usr/curl_path/curl) so that cmake could generate link.txt as below?
/usr/bin/c++ CMakeFiles/demo.dir/sample.cpp.o -o demo -L/home/user/sample_cmake/usr/lib/lib64 -L/home/user -rdynamic /usr/curl_path/curl -lopenssl -Wl,-rpath,/home/user/sample_cmake/usr/lib/lib64:/home/user
i know i can define libucrl path directly as below which will solve my issue ,
target_link_libraries(demo /usr/curl_path/curl openssl)
but iam looking for something like SET or any other cmake environment variable which i can define inside toolchain.cmake file so that cmakelist.txt is untouched ,in simple words how do i specify those libraries's path to cmake which are going use inside target_link_libraries
If your CMake version is less than 3.12, you need to use this old method. See:
https://cmake.org/cmake/help/v3.10/module/FindCURL.html
cmake_minimum_required(VERSION 3.10)
project(program)
find_package(CURL REQUIRED)
if (CURL_FOUND)
add_executable(program main.cpp)
target_link_libraries(program ${CURL_LIBRARIES})
target_include_directories(program PRIVATE ${CURL_INCLUDE_DIRS})
endif()
There is a new method for CMake 3.12 and later using imported targets. See the new alternative FindCurl.
cmake_minimum_required(VERSION 3.12)
project(program)
find_package(CURL REQUIRED)
if (CURL_FOUND)
add_executable(program main.cpp)
target_link_libraries(program CURL::libcurl)
endif()
I found out that this issue can be solved by two methods (first method is similar to this)
second method is by adding below two lines of code to your cmakelist.txt file before calling target_link_directories
add_library( curl SHARED IMPORTED)
set_property(TARGET curl PROPERTY IMPORTED_LOCATION "${CURL_LIBRARY}")
where CURL_LIBRARY is the path for libcurl.so specified in toolchain.cmake
unfortunately i didn't find any solution to solve this issue without touching cmakelist.txt.

How to get cmake generate -std=c++14 flag for qcc compiler

I'm trying to cross compile some c++ library for QNX neutrino using cmake. In CMakeLists.txt file I specified CMAKE_CXX_STANDARD 14 required, but the resulting compiler command line does not contain the -std=c++14 option.
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
I've tried using target compile features:
target_compile_features(my_library PRIVATE cxx_std_14)
but that gives me the following error:
CMake Error at CMakeLists.txt:53 (target_compile_features):
target_compile_features no known features for CXX compiler
"QCC"
version 5.4.0.
When I'm using check_cxx_compiler_flag feature, it seems to recognize the option:
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-std=c++14 CXX14_SUPPORT)
if(CXX14_SUPPORT)
message("c++14 support found")
else()
message("c++14 unsupported")
endif()
This outputs message
c++14 support found
Running qcc manually it accepts the -std=c++14 option just fine and the code using std::make_unique compiles just fine.
Also using the native compiler (Ubuntu 18.04, gcc) everything work fine with cmake generated makefiles. make VERBOSE=1 displays the following command line (I removed some directories):
/usr/local/bin/c++ -Dshm_transfer_EXPORTS -I... -fPIC -std=gnu++14 -o CMakeFiles/shm_transfer.dir/src/SharedMemoryTransfer.cpp.o -c .../SharedMemoryTransfer.cpp
as opposed to the command line using qcc toolchain:
.../qnx700/host/linux/x86_64/usr/bin/qcc -lang-c++ -Vgcc_ntox86_64 -lang-c++ -Dshm_transfer_EXPORTS -I... -fPIC -o CMakeFiles/shm_transfer.dir/src/SharedMemoryTransfer.cpp.o -c .../SharedMemoryTransfer.cpp
I would have expected the cmake command to recognize that qcc supports the -std=c++14 option and generates the corresponding command lines because of the CMAKE_CXX_STANDARD setting.
Use
set_property(TARGET ${PROJECT_NAME} PROPERTY LINKER_LANGUAGE CXX)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14)
. Using this you can stick the compiler setting to the target, while global flags are dis encouraged and can be overwritten by other cmake consumers. This the reason I assume why the deprecated set(CMAKE_CXX_STANDARD 14) did not help you: I can not see your full CMakeLists.txt and bet you have many sub folders and other targets, which could reset the CMAKE_CXX_STANDARD them selfs. Also make sure of the ordering of the CMake commands.
And you can replace ${PROJECT_NAME} with my_library if you want.
add_compile_options(-std=gnu++14)
Add this to your project level CMakeLists.txt file, not in toolchain.

Error with variables when invoking CMake from CMake

I need to invoke cmake from within cmake so that I can have binaries built before project files are generated. I have the following CmakeLists.txt:
cmake_minimum_required(VERSION 3.2)
project(StarEngine)
set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
#copy the other cmake file into where we'd like to invoke cmake
configure_file(deps-CMakeLists.txt deps/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps)
#eventually binaries will be built, for now this doesn't accomplish anything
execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps)
And its friend, deps-CmakeLists.txt, a test script:
set(GENERATED_DIR "test")
MESSAGE( STATUS ${GENERATED_DIR} )
In the following file structure:
Project
build
Code
CmakeLists.txt
deps-CmakeLists.txt
No matter what I put in for the variable value, it is blank when displayed in MESSAGE. I imagine this is weird behavior resulting from invoking cmake from cmake. I had a bunch of other strange errors to, but I suspect if I can figure out this one that will help crack them all.
Thanks to #Florian, the problem was with variable replacement and I needed to add the COPYONLY option to configure_file

CMake: How to add dependency on linker script for executable

I have a CMake script where the final executable is linked with my own linker script:
cmake_minimum_required(VERSION 3.1)
project(test_app)
set(LINKER_SCRIPT "linker.ld")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T ${LINKER_SCRIPT}")
add_executable(${PROJECT_NAME}.elf
main.cpp
startup.cpp
)
How do I make an executable dependent also on the linker script file (trigger linking if linker.ld was changed)?
You can add a LINK_DEPENDS property to your executable target, using set_target_properties. Add the following line after your add_executable command:
set_target_properties(${TARGET_NAME} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
The first argument to set_target_properties is the target name, i.e. the first argument you passed to add_executable.
I found this mail which described three possible ways for forcing an executable to be dependent on a linker script. Its author prefers this way:
CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(LINKERSCRIPT C)
FILE(WRITE main.c "void main(){}")
# dummy.c must exist:
ADD_EXECUTABLE(EXE main.c dummy.c)
# linkerscript must exist:
SET_SOURCE_FILES_PROPERTIES(
dummy.c PROPERTIES OBJECT_DEPENDS ${CMAKE_SOURCE_DIR}/linkerscript
)
Here dummy.c is an empty file, which is listed for the add_executable() command only for make resulted executable dependent on the linker script via the OBJECT_DEPENDS property.