CMake compile C++ file in custom command - c++

I'm trying to precompile a header file in GCC with the following command:
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/all.hpp.gch
COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} -o ${CMAKE_BINARY_DIR}/all.hpp.gch ${CMAKE_CURRENT_SOURCE_DIR}/all.hpp
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/all.hpp
COMMENT "Generating precompiled headers"
)
However, I don't get CMAKE_CXX_FLAGS to expand into flags I've set using CMake's add_definitions(). What is the correct way of compiling in add_custom_command()?

I don't believe that add_definitions() adds its arguments to CMAKE_CXX_FLAGS. In fact, as far as I can tell they aren't saved anywhere (apart from arguments beginning with -D or /D which get added to COMPILE_DEFINITIONS).
The simplest way to solve that would be to, whenever calling add_definitions(), to also manually add those flags to CMAKE_CXX_FLAGS.
To see what is in CMAKE_CXX_FLAGS at any point, you can do
message(STATUS ${CMAKE_CXX_FLAGS})
or check the CMakeCache.txt in the build directory (or via ccmake or cmake-gui).

Related

How to properly set CMake flags in CMakeLists.txt

I'm having trouble setting up options and CMake variables and getting them propagated to the CMake GUI.
For example, the following lines are in my CMakeLists.txt file:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -tR -DPOCO_DLL")
message("CMake flags: " ${CMAKE_CXX_FLAGS})
When running configure in the CMake GUI it prints "CMake flags: -tM -tR -DPOCO_DLL" indicating that setting the CMAKE_CXX_FLAGS "works".
The GUI however don't get updated and only shows "-tM" on the CMAKE_CXX_FLAGS line.
What is the proper way of setting up these CMAKE options in the CMakeLists file so they get propagated to the CMake GUI?
The trick is to set CMAKE_CXX_FLAGS before project(...) statement. But this will not be enough; you will also need to put it into the cache.
Also, if you plan to support setting it initially from the command line interface, and/or -C cmake option (locad initial cache), you will need to force put it into the cache, as shown:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -tR -DPOCO_DLL" CACHE STRING "Default CXX options" FORCE)
...
...
project(MyProject)
....
On the other hand, be very careful, because you are setting command line options at the moment you know nothing about the compiler, that is by default determined during execution of project statement.
Implicitly, this renders your CMakeLists.txt compiler dependant.
At the end, here is documentation about set cmake command

linking librarys as a part of flags in toolchain file in cmake

i've tried to add PROFILE to the CMAKE_BUILD_TYPES. For this I need to add -finstrument-functionsto the CMAKE_CXX_FLAGS in the toolchain file and link the belonging library with the absolut path in the CMakeLists.txt via target_link_libraries. So far so good and unproblematic.
But when refreshing the buildinformations cmake checks if the compiler stil does it's job. And now "is not able to compile a simple test program", due to the lack of the needed library, which is linked later in the CMakeLists.
So I commented the -finstrument-functions flag and the testprogramm could be compiled.
I've tried to:
- Set librarie and path as a part of the CXX flags with -L -l:
Use the link_directories(<dir>) command as well as SET(CMAKE_LINK_DIRECTORIES_BEFORE <Path> ) and SET(CMAKE_LIBRARY_PATH <Path>)
Set variables in the toolchainfile and call them later in the cmakelists:
SET(ADDITIONAL_PROFILE_LIBRARY "$ENV{QNX_BASE}/target/qnx7/armle-v7/usr/liblibprofilingS.a")
SET(ADDITIONAL_PROFILE_FLAGS "-finstrument-functions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" "${ADDITIONAL_PROFILE_FLAGS}")
add_executable(toolchainTester main.cpp)
target_link_libraries(toolchainTester ${ADDITIONAL_PROFILE_LIBRARY})
But then getting the error: mingw32-make.exe[3]: *** No rule to make target 'C:/qnx700/target/qnx7/armle-v7/usr/liblibprofilingS.a', needed by '../out/profileout'. Stop.
Got anyone any more ideas? Thanks in advance.
If there anyone out there, looking for the same workaround how to manage different flags and libraries for different profiles, this is one working way:
First set variables in the toolchainfile
SET(ADDITIONAL_PROFILE_LIBRARY "$ENV{QNX_BASE}/target/qnx7/armle-v7/usr/lib/libprofilingS.a")
SET(ADDITIONAL_CXX_FLAGS "-finstrument-functions")
The call/overright them in the CMakeLists.txt
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" "${ADDITIONAL_CXX_FLAGS}")
add_executable(toolchainTester main.cpp)
target_link_libraries(toolchainTester ${ADDITIONAL_PROFILE_LIBRARY})

How to insert a flag at the end of the execution command line using CMake? [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

Compile without linking

I have a project set up with CMake, and I would like to build one object file in the project and output its llvm IR representation, in order to systematically inspect the generated output.
What I have so far is this:
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
separate_arguments(COMPILE_FLAGS UNIX_COMMAND ${CMAKE_CXX_FLAGS})
list(APPEND COMPILE_FLAGS "-S" "-emit-llvm" "-o" "example1.llvm")
add_custom_command(
TARGET example1 #example1 is the target that builds the actual executable
POST_BUILD
COMMAND ${CMAKE_CXX_COMPILER}
ARGS ${COMPILE_FLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/calculator1.cpp
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Output the llvm IR representation"
)
endif()
Unfortunately ${CMAKE_CXX_FLAGS} does not contain all the arguments passed to clang in the actual compilation. I miss at least the extra include directories, and probably something else.
I tried
get_target_property(MYVAR example1 COMPILE_FLAGS)
and
get_property(
MYVAR
TARGET example1
PROPERTY COMPILE_FLAGS )
But they both fail.
How do I get all the options passed to the compiler (and not the linker)?
Should I take an entirely different approach?
Do you generate Makefile:s out of CMake? In that case you can use the property RULE_LAUNCH_COMPILE:
RULE_LAUNCH_COMPILE Specify a launcher for compile rules.
Makefile generators prefix compiler commands with the given launcher
command line. This is intended to allow launchers to intercept build
problems with high granularity. Non-Makefile generators currently
ignore this property.

Add custom build step in CMake

I'm trying to add a custom build step in CMake that generates some files. I haven't found a description how it works.
I have an project where source, header & implementation files have to be generated by ODB for C++. ODB takes class headers as arguments and generates source files that I want to use in my project.
Right now I have the following command in my CMakeLists.txt:
add_custom_command(TARGET ${PROJECT_NAME}
PRE_BUILD
COMMAND odb -o /home/david/dev/ --std c++11 -I/home/david/dev/ -d sqlite --generate- query --generate-schema ${PROMOTER_LIB_PREFIX}/entities/person.hpp
DEPENDS ${PROJECT_NAME}
VERBATIM
)
For a file person.hpp ODB should generate person-odb.hxx, person-odb.cxx, person-odb.ixx but the CMake command I''ve used doesn't generate anything. In a terminal this command works fine.
What am I doing wrong?
EDIT: The problem can be solved by adding the following lines:
set(FAKE_TARGET fakeTarget)
add_custom_target(fakeTarget
odb -o /home/david/dev/ --std c++11 -I/home/david/dev/ -d sqlite --generate-query --generate-schema ${PROMOTER_LIB_PREFIX}/entities/person.hpp
)
add_dependencies(${PROJECT_NAME} ${FAKE_TARGET})
For me, with something similar, I just use :
add_custom_command(TARGET ${PROJECT_NAME}
PRE_BUILD
COMMAND odb -o /home/david/dev/ --std c++11 -I/home/david/dev/ -d sqlite --generate- query --generate-schema ${PROMOTER_LIB_PREFIX}/entities/person.hpp
)
We don't use DEPENDS or VERBATIM.
The DEPENDS option specify that the command must be executed only after that the project you gave to this option is built.
EDIT :
Note that the PRE_BUILD option is only supported on Visual Studio 7 or later. For all other generators PRE_BUILD will be treated as PRE_LINK.
Maybe that's why it doesn't work for you.
A work around could be (a bit ugly) :
Create a fake project
Add your custom command on it as POST_BUILD
Make you current project dependent on the fake one
Way I'm using it is:
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/gen_icinstrtab.hpp
COMMAND xsltproc --output ${CMAKE_CURRENT_BINARY_DIR}/gen_icinstrtab.hpp ${CMAKE_SOURCE_DIR}/xml/genictabc.xslt ${CMAKE_SOURCE_DIR}/xml/icminstr.xml
)
add_executable(
du4
${CMAKE_CURRENT_BINARY_DIR}/gen_icinstrtab.hpp
.
.
.
)
The key was to add even .hpp files into add_executable block.