I understand that target_include_directories() can be used in conjunction with PUBLIC, INTERFACE, or PRIVATE to specify the scope or privacy of the directories. But a lot of antiquated code still uses include_directories(), and I'm not sure how these directories are treated by the targets that use them.
Is using include_directories() essentially the same as using target_include_directories(MyTarget PRIVATE ...)? I have seen this similar question, but is there no default scoping behavior with include_directories() either?
Is using include_directories() essentially the same as using target_include_directories(MyTarget PRIVATE ...)?
Yes, for every target, affected by include_directories (that is, in the current CMakeLists.txt and below), it has the same effect as PRIVATE keyword in target-specific version of the command.
Documentation for include_directories says, that the command assigns INCLUDE_DIRECTORIES property of the targets and directories:
The include directories are added to the INCLUDE_DIRECTORIES directory property for the current CMakeLists file. They are also added to the INCLUDE_DIRECTORIES target property for each target in the current CMakeLists file.
and the directory property affects on further target's ones:
This property is used to populate the INCLUDE_DIRECTORIES target property.
Exactly INCLUDE_DIRECTORIES target property is affected by the PRIVATE keyword of target_include_directories command:
PRIVATE and PUBLIC items will populate the INCLUDE_DIRECTORIES property of <target>. PUBLIC and INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES property of <target>.
Related
I have a header only library I want to write a CMake file for, to be used in other projects. To do this I need to declare the library an interface target. The header files are then added by CMakeList.txt files in subfolders.
Now I want to get the list of source files to run clang-format on them. But get_target_property does not work on interface targets. Is there any way to extract the sources (or headers) from an interface target?
This is the code I have at the moment (not working)
make_minimum_required(VERSION 3.12)
project(foo
LANGUAGES CXX
VERSION 1.0.0)
add_library(bar INTERFACE)
# add header files in sub folders with
target_sources(bar INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/header.h"
)
# this gives the error
get_target_property(MY_SOURCES bar SOURCES)
The error message
INTERFACE_LIBRARY targets may only have whitelisted properties. The
property "SOURCES" is not allowed.
I tried to link the interface target into a real target and get the sources that way, but I only got the sources added directly to the second target, not the sources from the interface target
Because your target is declared as INTERFACE, the target_sources() command populates the INTERFACE_SOURCES property of the target, not SOURCES. From the docs:
The INTERFACE, PUBLIC and PRIVATE keywords are required to specify the scope of the following arguments. PRIVATE and PUBLIC items will populate the SOURCES property of <target>. PUBLIC and INTERFACE items will populate the INTERFACE_SOURCES property of <target>.
Try grabbing the INTERFACE_SOURCES property instead:
add_library(bar INTERFACE)
# add header files in sub folders with
target_sources(bar INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/header.h"
)
# this gives the error
get_target_property(MY_SOURCES bar INTERFACE_SOURCES)
Is there a way to change a shared library's extension, only on windows from ".dll" to something else?
add_library(mylib SHARED <src>)
So instead of creating a mylib.dll file i need it to be something else like mylib.dla.
Set the target's SUFFIX property, i.e.:
add_library(mylib SHARED <src>)
set_target_properties(mylib PROPERTIES SUFFIX ".dla")
set(CMAKE_STATIC_LIBRARY_SUFFIX ".dla")
will change all suffixes but will work for you as well
In foo/CMakeLists.txt, based on this and this, I have the following
SET (EXTERNAL_LIB_ROOT "../../external_libs/")
ADD_LIBRARY (avcodec-debug STATIC IMPORTED)
SET_PROPERTY (
TARGET avcodec-debug PROPERTY IMPORTED_LOCATION
${EXTERNAL_LIB_ROOT}/libavcodec-0.8.10.a)
In bar/CMakeLists.txt I have this:
# old way uses system libraries
#TARGET_LINK_LIBRARIES (bar avformat avcodec avutil)
# new way uses local debug builds
TARGET_LINK_LIBRARIES (bar avformat avcodec-debug avutil)
When I run make I get
/usr/bin/ld: cannot find -lavcodec-debug
If I revert to the old way, build, touch foo/CMakeLists.txt and rebuild, CMake's configuration output indicates that avcodec-debug is being found by the build system.
So why can't I add it as a dependency?
As it mentioned above by Angew the visibility for imported library differs, though you can extend it using GLOBAL modifier. It might be enough for you to modify add_library call next way:
ADD_LIBRARY(avcodec-debug STATIC IMPORTED GLOBAL)
Imported targets do not follow the same visibility rules as non-imported targets. While non-imported targets are global (visible and accessible from anywhere after they're defined), imported targets are only visible in the CMakeLists.txt where they are defined and below (in directories added by add_subdirectory() in this defining CMakeList).
Since foo is a sibling of bar in your case, the target name avcodec-debug is not visible inside bar/CMakeLists.txt, so it's treated as a normal library name.
It's generally preferred to define imported targets in files you include rather than in their own projects. So change (or extract the relevant parts of) foo/CMakeLists.txt into foo/avcodec.cmake and then in the top-level CMakeList, replace
add_subdirectory(foo)
with
include(foo/avcodec.cmake)
Is there a way to force doxygen to ignore all class extensions in an Objective-C project without using preprocessor directives?
I use class extensions extensively in my Class.m files for my private attributes. When I use doxygen to generate documentation for my application, the generated class list includes all of my "secret" class extensions. I would like to hide these extensions from the generated documentation.
I can get doxygen to ignore a particular class extension by using the doxygen preprocessor and surrounding the extension in the Class.m with a #ifndef/#endif. I really don't like adding this to all of my Class.m files that have the internal extensions, because I feel that I am adding more clutter to my files.
If you want exclude all the class continuation add this row to the Doxy file
EXCLUDE_SYMBOLS = *()
The class extensions can be excluded without changing the source code. This can be done by listing the class extensions in the exclude_symbols setting. See the sample screenshot:
I have a section of code that is conditionally activated depending on a #define, like this:
#ifdef VARIABLE
code.function();
#endif
The cmake script has an 'options' command that sets the VARIABLE like this:
option(VARIABLE "Want to use VARIABLE?" ON)
if(VARIABLE)
message(STATUS "VARIABLE")
set(VARIABLE_FLAG "-DVARIABLE")
endif()
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${VARIABLE_FLAG} -Wall")
I'm using cmake to build the project and qtcreator as IDE. My problem is that qtcreator thinks that VARIABLE is not defined so my code has is not highlighted, but when I build it on a console, VARIABLE is defined. So, what parameters should I pass to qtcreator to run cmake, so that it knows VARIABLE is defined and highlights my code? Is there a way to do this?
Ps: I just use qtcreator to edit files, the build part is done via console commands.
Another alternative would be to use a configured header file, and include it only where you need the definition:
# in CMakeLists.txt
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/my_defs.h.in
${CMAKE_CURRENT_BINARY_DIR}/my_defs.h
)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
and
// in my_defs.h.in
#cmakedefine VARIABLE
// configure_file converts #cmakedefine of a named CMake variable
// into a C++ #define of a C++ pre-processor symbol
and finally
// in various C++ source or header files, but only as needed:
#include "my_defs.h"
#ifdef VARIABLE
doSome_VARIABLE_SpecificStuff();
#endif
I do not use QtCreator regularly, so I don't know if this technique works in terms of their syntax highlighting, but I'd assume it would, since they must read header files in order to do a proper job of it...
Take a look at add_definitions(). It adds a preprocessor-define to the compiler and can be used like any ordinary #define:
add_definitions( -DVARIABLE )
However... I am not sure if this will make qtcreator pick it up as a 'known variable'.
You can also use the project_name.config file. It is specifically used for your need. You can add defines which are only interpreted by QtCreator for highlighting and auto-completion.
This file is normally in the root folder of your project.