How to globally override compiler in qmake with subprojects? - qt5

Can I somehow override define QMAKE_CXX globally for all subprojects of a .pro file?
Placing this statement to the top project file did not change the compiler in subprojects. It only works if I copy it to every .pro file.
I would like to define QMAKE_CXX = ccache $$QMAKE_CXX using a command line argument for qmake

Related

Using Cmake to add compiler options to existing cmake

I have a submodule with a CMakeLists.txt, which I would like to "amend" in a way to make it work for my specific purpose (I need to add compiler flags and a different output directory) The output is a static library. My current approach is as follows:
I have a CMakeLists.txt in the root directory, which adds the submodule CMakeLists.txt via add_subdirectory() like so:
set(CMAKE_CXX_FLAGS "-my_needed_flags "
add_subdirectory(SubmoduleLibrary)
set_target_properties(SubmoduleLibrary PROPERTIES ARCHIVE_OUTPUT_DIRECTORY output_folder)
add_custom_target(BuildLib)
add_dependencies(BuildLib SubmoduleLibrary)
Now this seems to work in some ways (the output directory is correctly chosen). But I get linker errors which I don't get when I compile the library adding the flags etc to the original CMakeLists.txt.
What is the correct way to build a library from an existing CMakeLists.txt with added parameters?

CMAKE - check if target is compilable

My project consists of multiple targets. I want to specify compile options for all of them with
command "target_compile_options"
I get a list of targets using macros from CMake - remove a compile flag for a single translation unit:
macro(apply_global_cxx_flags_to_all_targets)
separate_arguments(_global_cxx_flags_list UNIX_COMMAND ${CMAKE_CXX_FLAGS})
get_property(_targets DIRECTORY PROPERTY BUILDSYSTEM_TARGETS)
foreach(_target ${_targets})
target_compile_options(${_target} PUBLIC ${_global_cxx_flags_list})
endforeach()
unset(CMAKE_CXX_FLAGS)
set(_flag_sync_required TRUE)
endmacro()
But I receive errors:
target_compile_options called with non-compilable target type
as some of targets doesn't require compiling. Is there a way to check if project is compilable? I want to use "target_compile_options as I need to remove some options for one subproject (as in mentioned thread)
Is there a way to check if project is compilable?
Yes, get the type of the target and check if it's an executable or a library and if it's not an INTERFACE library.
I want to specify compile options for all of them
Consider using add_compile_options at root folder instead.

CMake setting to Ninja rebuild when header change?

Apparently, Ninja has to be configured to treat headers as dependencies: https://ninja-build.org/manual.html#ref_headers.
How do I tell CMake to generate this into my build.ninja?
If I look into my build.ninja files generated with CMake for e.g. GCC I do have the necessary dependency file entries automatically generated (see DEP_FILE):
#=============================================================================
# Object build statements for EXECUTABLE target MyExe
build CMakeFiles/MyExe.dir/foo.cc.obj: CXX_COMPILER ../foo.cc
DEP_FILE = CMakeFiles/MyExe.dir/foo.cc.obj.d
FLAGS = -fdiagnostics-color=always -Wconversion
OBJECT_DIR = CMakeFiles\MyExe.dir
OBJECT_FILE_DIR = CMakeFiles\MyExe.dir
And the dependency checking works as expected. Just touch or change one of the header dependencies and ninja will automatically rebuild the necessary sources.
There is the file property OBJECT_DEPENDS, which can be used to specify the dependency on other files of any objects created from a specific file.
From the docs:
Additional files on which a compiled object file depends.
Specifies a ;-list of full-paths to files on which any object files compiled from this source file depend. On Makefile Generators and the Ninja generator an object file will be recompiled if any of the named files is newer than it. Visual Studio Generators and the Xcode generator cannot implement such compilation dependencies.
This property need not be used to specify the dependency of a source file on a generated header file that it includes. Although the property was originally introduced for this purpose, it is no longer necessary. If the generated header file is created by a custom command in the same target as the source file, the automatic dependency scanning process will recognize the dependency. If the generated header file is created by another target, an inter-target dependency should be created with the add_dependencies() command (if one does not already exist due to linking relationships).
To set this property on a given source file, use:
set_property(SOURCE first.cpp second.cpp
APPEND PROPERTY OBJECT_DEPENDS "${PROJECT_SOURCE_DIR}/inc/header1.h;${PROJECT_SOURCE_DIR}/inc/header2;${PROJECT_SOURCE_DIR}/inc/global_deps.h"

CMake and FindProtobuf

I'm using the FindProtobuf module in a project where the protocol buffer files are in a sub-directory. I want the CMakeLists.txt file in that sub-directory to invoke protoc to generate the CPP Files. My project folder structure is like this:
cammy/CMakeLists.txt # Root CMakeLists.txt
cammy/protofiles/test.proto # protofile
cammy/protofiles/CMakeLists.txt
I have the include(FindProtobuf), the find_package invocation and the call to PROTOBUF_GENERATE_CPP in the CMakeLists.txt file in protobuf folder.
The executable build step is in the Root CMakeLists.txt file and I add the generated files
to the target executable in this file
ie.
add_executable( ${EXEC} ${SRCS} ${PROTO_SRC} ${PROTO_HEADER} )
target_link_libraries( ${EXEC} ${PROTOBUF_LIBRARIES} )
are both defined in the root CMakeLists.txt
When I run cmake, it does not run protoc to generate the Source files even though I expilicitly tie generated sources to the executable thereby creating a dependency.
When I move all the contents of CMakeLists.txt in the protofiles folder into the root CMakeLists.txt, the proto files are compiled.
Can anyone help me with this? I want all the protocol buffer building stuff to go in the CMakeLists.txt file created in the protofiles folder.
I also noticed that variables generated in the inner CMakeLists.txt ( like PROTO_SRC ) are defined in the inner file when printed ( ie I get the correct generated CPP filename ) but when I print the same variable in the root file.. it is empty. Its almost as though I need to "export" (if there were a way in cmake ) the variables out to the root folder.
Any help would be much appreciated.
Thanks
Kartik
I think [FindProtobuf][0] isn't really meant to be used this way. From its docs:
NOTE: The PROTOBUF_GENERATE_CPP macro & add_executable() or add_library()
calls only work properly within the same directory.
You're trying to use the PROTOBUF_GENERATE_CPP macro in a subdirectory, and although the CMake docs don't really make it clear, a subdirectory introduces a new scope for variables. This means that any variables set or modified in the subdir scope don't affect similarly-named variables in the parent scope. Hence the reason for PROTO_SRC being available in your protofiles dir, but not in the parent.
The way to pass variables up a scope is to use [set(... PARENT_SCOPE)][1], so in protofiles/CMakeLists.txt you could do:
PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER test.proto)
set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS} PARENT_SCOPE)
set(PROTOBUF_LIBRARIES ${PROTOBUF_LIBRARIES} PARENT_SCOPE)
set(PROTO_SRC ${PROTO_SRC} PARENT_SCOPE)
set(PROTO_HEADER ${PROTO_HEADER} PARENT_SCOPE)
However, this still doesn't get us all the way!
CMake doesn't actually invoke the protoc compiler to generate the .pb.h and .pb.cc files - it uses [add_custom_command][2] to do this. The custom command specifies the .pb.h and .pb.cc files as outputs, and the custom command is only invoked (i.e. protoc executed) if a subsequent target which depends on these files is built.
So, at configure time (when CMake executes) these files don't exist. This is a problem if you try to add them as sources to an add_library or add_executable command - CMake needs to be told that these files don't exist when it runs, but that they will exist at build time.
The way to do that is to set the [GENERATED][3] property to TRUE for these files. The PROTOBUF_GENERATE_CPP macro does that automatically, but as with the variables, the property isn't populated up into the parent scope. So in your top-level CMakeLists.txt, you also need to add:
set_source_files_properties(${PROTO_SRC} ${PROTO_HEADER} PROPERTIES
GENERATED TRUE)
As you can see, using PROTOBUF_GENERATE_CPP in a different dir to the corresponding add_library/add_executable commands is a bit fragile. If you can avoid doing it, you probably should.
[0]: https://cmake.org/cmake/help/latest/module/FindProtobuf.html "CMake latest documentation for "FindProtobuf" module"
[1]: https://cmake.org/cmake/help/latest/command/set.html "CMake latest documentation for "set" command"
[2]: https://cmake.org/cmake/help/latest/command/add_custom_command.html "CMake latest documentation for "add_custom_command""
[3]: https://cmake.org/cmake/help/latest/prop_sf/GENERATED.html "CMake latest documentation for "GENERATED" source file property"

Renaming cpack automatic target

When you INCLUDE(CPack) in a CMakeLists.txt file, it adds a target named package to the generated build files. You can configure a lot of things about that generated target and how it operates, but I can't seem to find a way to change the name of the target itself; i.e., instead of a generated Makefile containing a target named package, I'd like it to contain one named (for example) bundle instead. Is there any way to do this?
CMake only adds the default package target if a package config file named CPackConfig.cmake exists in the outermost binary build directory. By forcing the CPack module to generate the package file under a different name, you can prevent the package target from being created:
set (CPACK_OUTPUT_CONFIG_FILE "${CMAKE_BINARY_DIR}/BundleConfig.cmake")
include(CPack)
You can manually add a bundle target then:
add_custom_target(bundle
COMMAND "${CMAKE_CPACK_COMMAND}"
"-C" "$<CONFIGURATION>" "--config" "${CMAKE_BINARY_DIR}/BundleConfig.cmake")
This is also true for the default package_source target. Use the variable CPACK_SOURCE_OUTPUT_CONFIG_FILE to override the default package configuration file name CPackSourceConfig.cmake.