Qt5, CMake, AUTOMOC and precompiled headers - visual-studio-2010

How to specify a precompiled header to the output of CMake (2.8.12.1) AUTOMOC ?
So far, in the CMakeLists.txt I've tried these two separately:
set(AUTOMOC_MOC_OPTIONS "-bstdafx.h")
set(AUTOMOC_MOC_OPTIONS "-fstdafx.h")
The generated AUTOMOC output when building the project (project_automoc.cpp) only contains the moc_xxx.cpp files:
/* This file is autogenerated, do not edit*/
/// <- stdafx.h should be here ?!?!
#include "moc_widget_fps.cpp"
#include "moc_widget_sysevents.cpp"

After some digging I decided to just turn the AUTOMOC feature off for projects that use precompiled headers:
set_target_properties (ProjectName PROPERTIES AUTOMOC FALSE)
# Set the headers that need moc'ing
file (GLOB MOC_FILES widget_filetransfer.h widget_main_menu.h widget_main_toolbar.h)
QT5_WRAP_CPP (MOC_SOURCES ${MOC_FILES})
...
# Force PCH for the generated MOC files
foreach (src_file ${MOC_SOURCES})
set_source_files_properties (${src_file}
PROPERTIES COMPILE_FLAGS "/Yustdafx.h /FIstdafx.h"
)
endforeach()

The correct variable to set is called CMAKE_AUTOMOC_MOC_OPTIONS. It is used to initialize the AUTOMOC_MOC_OPTIONS property of a target, i.e.:
set (CMAKE_AUTOMOC_MOC_OPTIONS "-bstdafx.h" "-fstdafx.h")
Also note that this will only make the Qt MOC compiler add the given includes to each generated moc_xxx.cpp file. The overall project_automoc.cpp will not be affected.

AUTOMOC_MOC_OPTIONS doesn't affect the project_automoc.cpp file. It contains options passed to moc to create "moc_widget_fps.cpp" and "moc_widget_sysevents.cpp". Those should contain your pch includes.

A perhaps more elegant way is to disable precompiled headers for the mocs_... file. This allows you to keep AUTOMOC:
append_to_source_file_property(
${CMAKE_CURRENT_BINARY_DIR}/<PROJECT_NAME_HERE>_autogen/mocs_compilation.cpp
COMPILE_FLAGS " /Y- ")
Alternatively if you can/are willing to change the name and contents of the precompiled header file, you can add this to it:
#ifdef HACK_FOR_TRICKING_MOC_INTO_INCLUDING_ME_IN_THE_MOCS_FILE_DO_NOT_DEFINE
Q_OBJECT
#endif
This will trick cmake into including it in the mocs_... file. You then need it to be at the top which requires a name change, files are sorted numbers first, then uppercase, then lowercase, so e.g. 1_precompiled.h should do the trick.

Related

cmake 'add_custom_command' to pre-process header files?

i'm working on a project requiring cmake. i'd like to add some custom rules to my makefile, but can't quite get my head around how to do it.
both c source files and header files are in the same directory. also in this same directory are a number of .def files, which are the sources for some of the header files #included in the source during compilation.
if i were to do this in a makefile, i'd use a simple rule like
.SUFFIXES: .def
.def.h:
$(PREPROC) $< > $#
how can i do this with cmake ??
i've tried various permutations of the following, both with and without cmake working directory specifications :
add_custom_command(
OUTPUT vvr_const.h
PRE_BUILD
COMMAND preproc vvr_const.def > vvr_const.h
DEPENDS vvr_const.def
)
add_custom_target(vvr_const.h DEPENDS vvr_const.def)
but the header file isn't generated by the time the c source file is compiled, so the compile fails. i've also tried a variation where i replace the last line above with
set_property(SOURCE main.c APPEND PROPERTY OBJECT_DEPENDS vvr_const.h)
in this case, the header file is correctly generated in advance, but make can't find it, and complains that there's no rule to make the target .h.
ideally this would be a general rule, like the make rule above, but i'm not opposed to making a separate rule for each of the .def files if that's what it takes.
cheers.
There are 2 problems with the add_custom_command approach you present:
You did not specify a working directory; by default the command is run in the build directory, not in the source directory.
You rely on shell functionality here (the redirect to a file). Even though this probably still works. You should go with an approach that does not rely on the shell.
To solve issues 1 and 2 I recommend creating a seperate cmake script file receiving the absolute paths to input and output files and using those in the custom command. This allows you to use execute_process to specify the file to write without relying on the platform.
preprocess_def.cmake
# preprocess def file
# parameters INPUT_FILE and OUTPUT_FILE denote the file to use as source
# and the file to write the results to respectively
# use preproc tool to get data to write to the output file
execute_process(COMMAND preproc "${INPUT_FILE}"
RESULT_VARIABLE _EXIT_CODE
OUTPUT_FILE "${OUTPUT_FILE}")
if (_EXIT_CODE)
message(FATAL_ERROR "An error occured when preprocessing the file ${INPUT_FILE}")
endif()
CMakeLists.txt
set(_INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.def")
set(_OUTPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.h")
# not necessary to use build event here, if we mark the output file as generated
add_custom_command(OUTPUT "${_OUTPUT_FILE}"
COMMAND "${CMAKE_BUILD_TOOL}" -D "OUPUT_FILE=${_OUTPUT_FILE}" -D "INPUT_FILE=${_INPUT_FILE}" -P "${CMAKE_CURRENT_SOURCE_DIR}/preprocess_def.cmake"
DEPENDS "${_INPUT_FILE}")
add_executable(my_target vvr_const.h ...)
set_source_files_properties(vvr_const.h PROPERTIES GENERATED 1)
Documentation from cmake:
PRE_BUILD
On Visual Studio Generators, run before any other rules are executed within the target. On other generators, run just before PRE_LINK commands.
So possibly your command is just running too late.

Get rid of CMake Rules folder

Is there a way to get rid of the CMake Rules folders in targets in Visual Studio?
In this case the game target uses cotire for precompiled header support and the omg target has a custom command that parses the .mix file and outputs the ..._gen.h file.
Also would it be possible to remove the CMakeLists.txt file from there too? I know it's there for convenience but in my workflow it isn't that useful.
EDIT: Started a second bounty because I really need this - these "CMake Rules" folders are bloating my solution explorer because I have 100+ projects which all have them!
I would accept anything - a CMake way, a VS way (some "solution explorer view" or macro or whatever)...
EDIT 2:
here is sort-of the cmake for the omg target:
add_library(omg SHARED D:/omg.cpp D:/omg.mix)
add_custom_command(OUTPUT D:/omg_gen.h MAIN_DEPENDENCY D:/omg.mix COMMAND python D:/mixify.py D:/omg.mix D:/omg_gen.h)
add_custom_target(${target}_gen_${mix_name_only} DEPENDS ${gen_header})
add_dependencies(omg omg_gen)
target_sources(omg PUBLIC D:/omg_gen.h)
so omg_gen.h is generated from omg.mix and then included in omg.cpp
The .rule files are needed by CMake to attach the custom commands to some "dummy" self-generated file, if there are no input files given. You can see this when you look at the .rule file properties of your Visual Studio project in question (see Custom Build Tool/General/Command Line).
If you're not changing the CMake script code containing those target, you can't get rid of them.
You can only move them into the project's root source folder or any other folder you specify.
I've successfully tested the following example:
cmake_minimum_required(VERSION 2.8)
project(NoRulesSourceGroup NONE)
# Overwrite the rule for "CMake Rules" with do-not-match-anything (-> root)
source_group("CMake Rules" REGULAR_EXPRESSION "^$")
# Move ".rule" files somewhere else
source_group("Some Other Source Group" REGULAR_EXPRESSION "\\.rule$")
add_custom_target(
${PROJECT_NAME}
COMMAND ${CMAKE_COMMAND} -E echo "Hello World"
)
Edit: You could also combine the above regular expression with a match for CMakeLists.txt:
source_group("Some Other Source Group" REGULAR_EXPRESSION "CMakeLists\\.txt|\\.rule$")
Edit: If you can modify your CMake script code, you should add to your add_custom_command() call:
MAIN_DEPENDENCY
Specify the primary input source file to the command. This is treated just like any value given to the DEPENDS option but also suggests to Visual Studio generators where to hang the custom command. At most one custom command may specify a given source file as its main dependency.
In your case you won't even need the additional custom target since you have a dependency through the header file. I've successfully tested the following derived from your question's example:
file(WRITE omg.cpp "")
file(WRITE omg.mix "")
add_library(omg SHARED omg.cpp omg.mix)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/omg_gen.h
MAIN_DEPENDENCY omg.mix
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/omg.mix ${CMAKE_CURRENT_BINARY_DIR}/omg_gen.h
)
target_sources(omg PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/omg_gen.h)
References
source_group()
Source/cmMakefile.cxx

gcc: passing list of preprocessor defines

I have a rather long list of preprocessor definitions that I want to make available to several C programs that are compiled with gcc.
Basically I could create a huge list of -DDEF1=1 -DDEF2=2 ... options to pass to gcc, but that would create a huge mess, is hard to use in a versioning-system and may at some time in the future break the command line length limit.
I would like to define my defines in a file.
Basically the -imacros would do what I want except that it only passes it to the first source file: (below from the gcc documentation):
-include file Process file as if #include "file" appeared as the first line of the primary source file. However, the first directory searched
for file is the preprocessor's working directory instead of the
directory containing the main source file. If not found there, it is
searched for in the remainder of the #include "..." search chain as
normal. If multiple -include options are given, the files are included
in the order they appear on the command line.
-imacros file Exactly like -include, except that any output produced by scanning file is thrown away. Macros it defines remain defined.
This allows you to acquire all the macros from a header without also
processing its declarations. All files specified by -imacros are
processed before all files specified by -include.
I need to have the definitions available in all source files, not just the first one.
Look at the bottom of this reference.
What you might want is the #file option. This option tells GCC to use file for command-line options. This file can of course contain preprocessor defines.
Honestly - it sounds like you need to do a bit more in your build environment.
For example, one suggestion is that it sounds like you should create a header file that is included by all your source files and #define all your definitions.
You could also use -include, but specify an explicit path - which should be determined in your Makefile/build environment.
The -imacros would work, if your Makefile were building each source file independently, into its own object file (which is typical). Its sounds like you're just throwing all the sources into building a single object.

About a deep header file in Makefile

Say I have a header file which is included by many source files, maybe with a very deep hierarchy. It is very boring to list this common header file in the prerequisites of each source object, and not sure whether there is an elegant solution. Thanks!
You can generate such dependencies with gcc -M. From TFM:
-M Instead of outputting the result of preprocessing, output a rule suitable for make describing the dependencies of the main source file. The preprocessor outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from -include or -imacros command line options.
Also see Generating Prerequisites Automatically.

Why would one use #include_next in a project?

To quote the iOS Documentation on Wrapper Headers:
#include_next does not distinguish between <file> and "file" inclusion, nor does it check that the file you specify has the same
name as the current file. It simply looks for the file named, starting
with the directory in the search path after the one where the current
file was found.
The use of `#include_next' can lead to great confusion. We recommend
it be used only when there is no other alternative. In particular, it
should not be used in the headers belonging to a specific program; it
should be used only to make global corrections along the lines of
fixincludes.
So, two questions, what is #include_next, and why would you ever need to use it?
It is used if you want to replace a default header with one of your own making, for example, let's say you want to replace "stdlib.h". You would create a file called stdlib.h in your project, and that would be included instead of the default header.
#include_next is used if you want to add some stuff to stdlib.h rather than replace it entirely. You create a new file called stdlib.h containing:
#include_next "stdlib.h"
int mystdlibfunc();
And the compiler will not include your stdlib.h again recursively, as would be the case with plain a #include, but rather continue in other directories for a file named "stdlib.h".
It's handy if you're supporting multiple versions of something. For example, I'm writing code that supports PostgreSQL 9.4 and 9.6. A number of internal API changes exist, mostly new arguments to existing functions.
Compatibility headers and wrapper functions
I could write compatibility headers with static inline wrapper functions with new names for everything, basically a wrapper API, where I use the wrapper name everywhere in my code. Say something_compat.h with:
#include "something.h"
static inline something*
get_something_compat(int thingid, bool missing_ok)
{
assert(!missing_ok);
return get_something(thingid);
}
but it's ugly to scatter _compat or whatever suffixes everywhere.
Wrapper header
Instead, I can insert a compatibility header in the include path when building against the older version, e.g. compat94/something.h:
#include_next "something.h"
#define get_something(thingid, missing_ok) \
( \
assert(!missing_ok), \
get_something(thingid) \
)
so the rest of the code can just use the 9.6 signature. When building against 9.4 we'll prefix -Icompat94 to the header search path.
Care is required to prevent multiple evaluation, but if you're using #include_next you clearly don't mind relying on gcc. In that case you can also use statement expressions.
This approach is handy when the new version is the "primary" target, but backward compatibility for an older version is desired for some limited time period. So you're deprecating the older versions progressively and trying to keep your code clean with reference to the current version.
Alternatives
Or be a sensible person, use C++, and use overloaded functions and template inline functions :p
include_next is used as a preprocessor directive to tell the compiler to exclude the search paths up to and including filename file.h from resolving to this header file. The typical need is when two header files of the same name need to be used. Use such features sparingly and only when absolutely necessary.
For example:
source file.c contents with the usual file.h from path 1:
#include <file.h>
int main() {
printf("out value: %d", out_val);
exit 0;
}
file.h header file in path 1 contents with file.h from path 2 included:
include_next instructs that path 1 sub directory not be used as search path for file.h and instead use path 2 sub directory as search path. This way you can have 2 files of the same name without the fear of invoking a circular reference to itself.
# include_next <file.h>
int out_val = UINT_MAX - INT_MAX;
file.h in path 2 contents
#define INT_MAX 1<<63 - 1
#define UINT_MAX 1<<64 - 1

Resources