Configuring Cmake file for library dependency [duplicate] - c

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

Related

How to include header files in external library in CMake

I have a C application which is running on Raspberry Pi 3 and currently, I have to build it on PI with Cmake. I am trying to build it on Ubuntu machine. I have added a CMAKE_TOOLCHAIN_FILE as described here.
I could run cmake. -DCMAKE_TOOLCHAIN_FILE without any problem but the "make" command is not successful and it can not find a header file inside one of the external library: "mirsdrapi-rsp". The error message is:
fatal error: mirsdrapi-rsp.h: No such file or directory
#include "mirsdrapi-rsp.h"
^
compilation terminated.
I have created a folder named "lib" and have put the "libmirsdrapi-rsp.so" file inside it.
my CMakeLists.txt is as below:
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -Wextra -v -g -D_XOPEN_SOURCE")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Wextra -v ")
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-v")
set (SDR_API_PATH ${CMAKE_SOURCE_DIR}/lib)
include_directories (include ${SDR_API_PATH})
include_directories("${CMAKE_SOURCE_DIR}/lib")
find_library(mirslocation NAMES mirsdrapi-rsp HINTS ${SDR_API_PATH} NO_CMAKE_FIND_ROOT_PATH)
message(STATUS ${mirslocation})
add_library(mirs STATIC IMPORTED)
set_target_properties(mirs PROPERTIES IMPORTED_LOCATION ${mirslocation})
target_link_libraries (raspberryPiDaemon mirs)
target_link_libraries(raspberryPiDaemon m)
Cmake is printing the right path of the library mirsdrapi-rsp while running "find_library" and as I mentioned I am getting the error message just while running "make" command and not "cmake" command.
My content of CMAKE_TOOLCHAIN_FILE is as below:
# Define our host system
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
# Define the cross compiler locations
SET(CMAKE_C_COMPILER ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc)
# Define the sysroot path for the RaspberryPi distribution in our tools folder
SET(CMAKE_FIND_ROOT_PATH ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot/SET)
# Use our definitions for compiler tools
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Search for libraries and headers in the target directories only
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
add_definitions(-Wall -std=c11)
Anybody knows how I can add the header file from mirsdrapi-rsp library to include path?
I guess that you're setting include_directories to the wrong path (it is set 2 times to ${CMAKE_SOURCE_DIR}/lib which must be the folder of libraries not the header files). Check again the correct location of the missing header file.
More precisely: you need to find the path of mirsdrapi-rsp.h and let CMake know it just like for find_library:
find_path(MIRSDRAPI_INCLUDE_DIRS NAMES mirsdrapi-rsp.h PATHS {proper-location})
if (MIRSDRAPI_INCLUDE_DIRS)
target_include_directories(raspberryPiDaemon PRIVATE ${MIRSDRAPI_INCLUDE_DIRS})
endif()
In addition, you can set the INTERFACE_INCLUDE_DIRECTORIES property to the library like this:
set_property(TARGET mirsdrapi-rsp APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${MIRSDRAPI_INCLUDE_DIRS})
This way, target_include_directories might be unnecessary and target_link_directories should be enough.

Correctly setting linker flags using CMake

I have a project with C and ASM (AT&T) source files that needs a linker script. My CMakeLists.txt looks something like this:
cmake_minimum_required(VERSION 2.8.4)
project(proj C ASM-ATT)
file(GLOB SOURCE_FILES *.c *.S)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -Wall -g -fno-stack-protector -pedantic")
add_executable(proj ${SOURCE_FILES})
set_target_properties(proj PROPERTIES LINK_FLAGS "-T${proj_SOURCE_DIR}/link.ld -melf_i386")
Strangely enough, building with make VERBOSE=1 reveals the following:
[ 14%] Linking C executable proj
(...)
/usr/bin/cc -m32 -Wall -g -fno-stack-protector -pedantic -T/path/to/link.ld -melf_i386 (all object files)
cc: error: unrecognized command line option '-melf_i386'
It seems that CMake is trying to use /usr/bin/cc as a C linker. I have played around with this and tried several different options (including setting CMAKE_LINKER and CMAKE_EXE_LINK_OPTIONS).
Also note that CMakeCache.txt contains a line saying
CMAKE_LINKER:FILEPATH=/usr/bin/ld
so it obviously is aware of ld and is simply using the C compiler to link the executable.
Any help would be greatly appreciated!
CMake by default invokes the linker indirectly through the compiler executable. The template command for linking executables is set up in the variable CMAKE_LANG_LINK_EXECUTABLE.
To have the compiler pass the flags on to the linker, use -Wl upon setting LINK_FLAGS, i.e.:
set_target_properties(
proj PROPERTIES LINK_FLAGS "-Wl,-T${proj_SOURCE_DIR}/link.ld,-melf_i386")

Compiling a C program and linking

Do I understand it correctly on how to use cmake for linking
cmake_minimum_required(VERSION 3.2)
project(Sdltest)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -lmingw32 -lSDL2main -lSDL2")
set(SOURCE_FILES main.c)
add_executable(Sdltest ${SOURCE_FILES})
I'm trying to link the sdl2 to my project but I get a lot of errors.
like /src/mingw-org-wsl/4.0-dev/src/libcrt/crt/main.c:91: undefined reference to `WinMain#16'
When I use gcc on cmd, it compiles perfectly
gcc main.c -o test -Wall -Werror -lmingw32 -lSDL2main -lSDL2
By the way I use clion 1.0.5
The problem is the flags, you mix compiler and linker flags. First of all this is problematic because the compiler flags aren't used when linking, and secondly because the GNU linker needs the libraries to come after the main source (or object) file on the command line, just like when you build manually.
You set the libraries by using the target_link_libraries command in your CMakeLists.txt file:
target_link_libraries(Sdltest mingw32 SDL2main SDL2)
Also, you're not building a C++ project, you're building a C project, so the flags variable should be CMAKE_C_FLAGS.
Finally, if you're wondering about the command and arguments that CMake uses when building, try making with VERBOSE set to non-zero, e.g.
make VERBOSE=1
I'm sure it's possible to add that argument to CLion.
PS.
If you want to enable more warnings, there are even more flags you could add, like -Wextra and -pedantic. Yes it might sometime give false positives, especially when including header files from external libraries, but I think it's better to have to many warnings when developing than to few.

CMake: Static and dynamic linking based on BUILD_TYPE

I am developing a small simulation software that depends on two libraries, the GSL and the libconfig. As a build system, I use CMake. For both the GSL and libconfig, I found cmake files and copied them into the cmake/ directory of my project.
The scenario is the following: I want the project to have several different build types, like debug, release, etc., but also a custom one called cluster, which adds -static to the GCC flags and links against the .a libraries of the GSL and the libconfig, which I assume exist.
My CMakeLists.txt looks like this so far:
# version
SET(PACKAGE_VERSION "1.0")
SET(PACKAGE_NAME "INTERFACE")
PROJECT(interface C CXX)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# dirs -----------------------------------------------------
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
FIND_PACKAGE(GSL REQUIRED)
INCLUDE_DIRECTORIES(${GSL_INCLUDE_DIRS})
SET(LIBS ${LIBS} ${GSL_LIBRARIES})
FIND_PACKAGE(LibConfig REQUIRED)
INCLUDE_DIRECTORIES(${LIBCONFIG_INCLUDE_DIRS})
SET(LIBS ${LIBS} ${LIBCONFIG_LIBRARIES})
CONFIGURE_FILE("res/config.h.in" "config.h")
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
SET_DIRECTORY_PROPERTIES(PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES "config.h"
)
# compilation ----------------------------------------------
ADD_EXECUTABLE( interface
interface.c interface.h config.h
helpers.c
output.c
lattice.c
genetic.c
)
# optional CFLAGS
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -std=c99")
SET(CMAKE_C_FLAGS_RELEASE "-O3 -ffast-math")
SET(CMAKE_C_FLAGS_CLUSTER "-O3 -ffast-math -static")
SET(CMAKE_C_FLAGS_DEBUG "-g")
SET(CMAKE_C_FLAGS_PROFILE "-g -ffast-math -pg")
TARGET_LINK_LIBRARIES(interface m ${LIBS})
# installation --------------------------------------------
INSTALL(TARGETS interface DESTINATION bin)
This adds the -static to the compiler, when I use -DCMAKE_BUILD_TYPE=cluster. The thing is, that it still links against the .so versions of the libs, which causes gcc to throw errors. At least the FindLibConfig.cmake scripts sets both a LIBCONFIG_LIBRARY and a LIBCONFIG_STATIC_LIBRARY variable, which I could use.
What is the most elegant or smart way to reach my goal?
Acording to cmake documentation, cmake uses the variable BUILD_SHARED_LIBS to determine the default for add_library().
If you set to ON cmake will assume all add_library() call will be as
add_library(target SHARED lib1 lib2 ...)
For example something like -DBUILD_SHARED_LIBS=ON on the cmake command line may do what you are asking.
I solved it like this:
The User can specify an additional variable -DSTATIC_LINKING=TRUE. Then, the script looks like this. (Only the important parts for the static linking and compilation are shown!)
# determine, whether we want a static binary
SET(STATIC_LINKING FALSE CACHE BOOL "Build a static binary?")
# do we want static libraries?
# When STATIC_LINKING is TRUE, than cmake looks for libraries ending
# with .a. This is for linux only!
IF(STATIC_LINKING)
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
ENDIF(STATIC_LINKING)
# set -static, when STATIC_LINKING is TRUE and set LINK_SEARCH_END_STATIC
# to remove the additional -bdynamic from the linker line.
IF(STATIC_LINKING)
SET(CMAKE_EXE_LINKER_FLAGS "-static")
SET_TARGET_PROPERTIES(surface PROPERTIES
LINK_SEARCH_END_STATIC 1)
ENDIF(STATIC_LINKING)

Tiny C Compiler (TCC) and winsock?

Can I use a socket library from TCC? I can't find any reference to winsock or sys/socket.h in the include directory.
If i remember correctly, winsock was part of the windows platform SDK (?) If so can I link that with TCC?
According to Tinycc-devel mailing list
you should give this a try:
tiny_impdef winsock.dll -o winsock.def
tcc yourcode.c winsock.def -o yourcode.exe
Use tiny_impdef.exe to export definitions from the DLL file using the command line:
tiny_impdef.exe wsock32.dll -o .\lib\wsock32.def
You will also need the header files for your source code to include them. MinGW's ones (such as winsock2.h, ws2tcpip.h, ws2spi.h...) can be reused with TCC.
The MinGW compiler can be downloaded from here. Just copy the headers you need from MinGW's include directory to TCC's include\winapi directory.
At compilation time, you will need to tell the compiler you are using the Windows socket library:
tcc.exe path\to\code.c -lwsock32 -o path\to\program.exe
tiny_impdef winsock.dll
copy winsock.def to lib/
run:
tcc -lwinsock yourcode.c -o yourcode.exe

Resources