CMake, static library and link time optimization - cmake

I'm trying to create static library with link time optimization using cmake and g++.
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra -pedantic -std=c++11"
)
if (CMAKE_COMPILER_IS_GNUCXX)
set(
CMAKE_STATIC_LINKER_FLAGS_RELEASE
"${CMAKE_STATIC_LINKER_FLAGS_RELEASE} -flto -fwhole-program"
)
endif()
add_library(
mylib STATIC
mylib.cpp
)
But when running typical
cmake -DCMAKE_BUILD_TYPE=Release ..
make
I'm getting following error:
/usr/bin/ar: two different operation options specified
link.txt file contains following commands:
/usr/bin/ar cq libmylib.a -flto -fwhole-program CMakeFiles/mylib.cpp.o
/usr/bin/ranlib libmylib.a
From what I understand from running ar --help the -flto -fwhole-program should be before libmylib.a in the first line. But I have no idea how to force CMake to put it there.
Is my assumption correct? And how can I resolve this?
EDIT: I'd like to add that I'm completely new to using LTO so if it doesn't make sense to use it for static libraries, please do tell me so.

-flto isn't a valid option for ar. You should instead use these flags for CMAKE_EXE_LINKER_FLAGS.

Related

CMake get all flags, includes and defines programatically

I'm using CMake 3.12 with linux and I try to extract all flags, includes and defines programatically from a target.
I found some help online, but it was always limited to the default settings induced by CMake.
For example with the variables :
CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE
...
Here I'm missing external flags.
I' stumbled upon the file "flags.make" located in the build folder of the project:
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.12
# compile C with /usr/bin/gcc-4.8
C_FLAGS = -O3 -DNDEBUG -fPIC
C_DEFINES = -DLINUX -DLINUX64 -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
C_INCLUDES =
Which is exactly what I need. Does anybody know how to access these variables within CMake?
Thank you!
Best regards
Fabian

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.

How to add the option `llvm-config --cxxflags --ldflags --libs` in CMake?

Does anyone know how to add the option `llvm-config --cxxflags --ldflags --libs` into CMake? The tricky part for me is the backtick `.
I need to config my CMake files to obtain a compilation command like:
g++ test.cpp -lclangBasic -I/usr/lib/llvm-6.0/include
-Wall `llvm-config --cxxflags --ldflags --libs`
I tried to use the following options, but they don't work:
add_compile_options(`llvm-config --cxxflags --ldflags --libs`)
# or
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} `llvm-config --cxxflags --ldflags --libs`")
Thank you in advance.
===============
Update 1.
Using the output from `llvm-config --cxxflags --ldflags --libs`, I can compile successfully with the following command:
g++ test.cpp -lclangBasic -I/usr/lib/llvm-6.0/include
-Wall -I/usr/lib/llvm-6.0/include -L/usr/lib/llvm-6.0/lib -lLLVM-6.0
I can pass -I/usr/lib/llvm-6.0/include by using include_directories(usr/lib/llvm-6.0/include).
But still, I don't know how to pass the part -L/usr/lib/llvm-6.0/lib -lLLVM-6.0 to CMake. Using link_directories and target_link_libraries like the following doesn't work for me:
link_directories(/usr/lib/llvm-6.0/lib)
target_link_libraries(test PUBLIC "LLVM-6.0")
Does anyone know to make them work in CMake?
===============
Update 2.
I have to add the following code into the file CMakeLists.txt to make CMake work.
add_library(LLVM-6.0 SHARED IMPORTED) # or STATIC instead of SHARED
set_target_properties(LLVM-6.0 PROPERTIES
IMPORTED_LOCATION "/usr/lib/llvm-6.0/lib/libLLVM-6.0.so"
INTERFACE_INCLUDE_DIRECTORIES "/usr/lib/llvm-6.0/include"
)
add_library(clangBasic SHARED IMPORTED) # or STATIC instead of SHARED
set_target_properties(clangBasic PROPERTIES
IMPORTED_LOCATION "/usr/lib/llvm-6.0/lib/libclangBasic.a"
INTERFACE_INCLUDE_DIRECTORIES "/usr/lib/llvm-6.0/include"
)
target_link_libraries(solidity PUBLIC "LLVM-6.0;clangBasic")
However, this looks manually, and I'm still looking for better solutions...
LLVM/Clang use CMake and provide a config module, so any project trying to use LLVM/Clang just need a find_package(Clang...) to bring the exported targets into a scope (and don't need to use any external tools (like llvm-config or pkg-config blah-blah)). Meaning that after Clang has found, you can use target_link_libraries(blah Clang::clangBasic ...) and no need to do any "manual import" or whatever ppl suggest in the comments...
As a quick check one may use the following command:
$ cmake --find-package -DNAME=Clang -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST
Clang found.
$ cmake --find-package -DNAME=Clang -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=COMPILE
-I/usr/lib/llvm-6.0/include
I used Clang 6.0 installed from the deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-6.0 main repo.

C Cmake setup - undefined reference to pow() (despite -lm)

I'm trying to build a project (with CLion) with the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.6)
project(alfa_1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c11 -Wall -Wextra -lm")
set(SOURCE_FILES
src/foo.h
src/foo.c
src/bar.h
src/bar.c
src/parser.h
src/parser.c)
add_executable(alfa_1 ${SOURCE_FILES})
In foo.c I use pow() function from math.h, which I include in foo.h. And obviously foo.h is included in foo.c. In bar.c I have main that is doing nothing. Now, standard command line compilation like this
gcc -o bar bar.c bar.h foo.h foo.c -lm
works fine but building the project yields undefined reference to pow. As one can see I included -lm flag in CmakeLists.txt file, so I don't get why this linking part is not working here
CMAKE_CXX_FLAGS are flags for the C++ compiler. -l is a linker flag. To link to a library, use this:
target_link_libraries(alfa_1 m)
You might also want to replace -std=c11 with use of CMAKE_C_STANDARD and related variables (CMAKE_C_STANDARD_REQUIRED, CMAKE_C_EXTENSIONS), and possibly replace use of CMAKE_CXX_FLAGS with a call to target_compile_options().
add the link of library in the cmakeList
add_library(math STATIC path/to/file.cpp)
add_executable(cmake_hello main.cpp)
target_link_libraries(cmake_hello math)
and in the class cpp
#include "path/to/file.hpp"
for mode detaills see this link
In Clion this configuration solved my problem:
cmake_minimum_required(VERSION 3.13)
project(K_Nearest C)
set(CMAKE_C_STANDARD 99)
add_executable(K_Nearest main.c point.h point.c group.c group.h)
target_link_libraries(K_Nearest m)
The important step was: target_link_libraries(K_Nearest m), it should come after add_executable(...) statement.

CMake not respecting command line options

Ubuntu 14_04, gcc 4.8.4, cmake 2.8.12.2
I wish to add additional options to UnitTest++. I added code coverage via UTPP_CODE_COVERAGE but leave it off for regular builds. This seemed to fail - nothing is in the Makefile that looks to be specified via the set(CMAKE_CXX_FLAGS option.
So I looked at whether the UTPP_AMPLIFY_WARNINGS command works
Whether I compile with it on or off, no difference is made to the Makefile.
At the terminal I compile with
$ cmake -G "Unix Makefiles" -DUTPP_AMPLIFY_WARNINGS=ON ../
But when I analyse the generated Makefile -Wall is nowhere to be found in the output. It's not even in the CMakeCache.txt
What am I doing wrong?
I can confirm what you have observed. There seems that the required warning level is already default in the CMakeLists.txt file and also the command set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") setting the -Wall flag is reached and executed (have tested this using message(). If there is no other answer here, at least you know you are not alone wondering how it comes.
cmake_minimum_required(VERSION 2.8.1)
project(UnitTest++)
option(UTPP_USE_PLUS_SIGN
"Set this to OFF if you wish to use '-cpp' instead of '++' in lib/include paths"
ON)
option(UTPP_INCLUDE_TESTS_IN_BUILD
"Set this to OFF if you do not wish to automatically build or run unit tests as part of the default cmake --build"
ON)
option(UTPP_AMPLIFY_WARNINGS
"Set this to OFF if you wish to use CMake default warning levels; should generally only use to work around support issues for your specific compiler"
ON)
...
# up warning level for project
if (${UTPP_AMPLIFY_WARNINGS})
# instead of getting compiler specific, we're going to try making an assumption that an existing /W# means
# we are dealing with an MSVC or MSVC-like compiler (e.g. Intel on Windows)
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
# message(STATUS "CMAKE_CXX_FLAGS MATCHES")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX")
else()
# message(STATUS "set(CMAKE_CXX_FLAGS")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
endif()
endif()