I'm porting a project to CMake, and struggling to find how to set header search paths (previously set with compiler flags e.g. -I "../../Source").
I currently have:
target_include_directories (jni-bridge PRIVATE
"../../Analysis"
"../../Source"
)
But this does not work. How should I set the paths, and what location are they relative to?
Internally, CMake uses absolute paths as include directories. If relative path is used with target_include_directories, then it is interpreted relative to the current source directory (${CMAKE_CURRENT_SOURCE_DIR}).
The above is true when generator expressions are not used.
Generator expression $<INSTALL_INTERFACE:..> may (and strongly recommended to) use relative path which is interpreted relative to the install prefix.
Generator expression $<BUILD_INTERFACE:...> should use absolute path.
In case someone comes here for a simple and direct code example, referring to the example at https://cmake.org/examples/, append the following to the top-level CMakeLists.txt file:
target_include_directories( helloDemo
path/to/header1.h
path/to/header2.h
)
Related
Context: I'm trying to come up with a fix for https://github.com/tensorflow/tensorflow/issues/37861 where header files of an external dependency are manually listed but that list is version specific and hence impossible to keep up to date.
What is happening:
tf_http_archive(name = "com_google_protobuf", system_build_file = clean_dep("//third_party/systemlibs:protobuf.BUILD") ...) is invoked
tf_http_archive is a repository_rule with effectively nothing but ctx.template("BUILD.bazel", ctx.attr.system_build_file, {...}, False)
In the protobuf.BUILD there is a list HEADERS = ["google/protobuf/any.pb.h", ...] which is passed to the hdrs argument of cc_library calls
a genrule apperantly symlinks those headers from $(INCLUDEDIR) into $(#D) (I'm not really familiar with Bazel but IIUC the latter is some internal build directory used later)
As I'm unfamiliar with Bazel in general I'll just assume the list of headers is required and there exists a $(INCLUDEDIR)/google/protobuf folder and is somewhere (else) on the system, e.g. /usr/local/include.
Is there any way to get all *.h and *.inc files in the format (i.e. relative to $(INCLUDEDIR)) via a glob or similar? The Bazel glob function doesn't work for absolute paths, so that can't be used.
I found https://github.com/bazelbuild/bazel/issues/8846 suggesting to use new_local_repository with a build_file and a path set to (in this case) $(INCLUDEDIR) but I don't see how that could be applied to the tf_http_archive (which has some conditions to either download the dependency or just use the system_build_file). This seems to also allow to avoid the symlinking (which I'm highly suspicious of anyway because that folder is added via -iquote but include style is #include <...>, see my comments in https://github.com/tensorflow/tensorflow/issues/37861)
Bonus points for people contributing to the issue or ideas why action_env environment variables seem to be ignored in a native.cc_library call.
Let's suppose I create a target as follows:
add_executable(app main.c)
install(TARGETS app
RUNTIME DESTINATION some/path}
)
How do I retrieve some/path with a generator expression?
$<TARGET_FILE:tgt> returns the full absolute path with the installation prefix
$<TARGET_FILE_DIR:tgt> does the same thing and includes the filename
$<TARGET_FILE_NAME:tgt> only returns the filename, not the path
What am I missing? Is there a property that contains this information?
There are neither generator expressions nor properties reflected installation path of particular target. All generator expressions you list reflect information about build location of the target.
There is $<INSTALL_PREFIX> generator expression, but it is available only when target is exported (install(EXPORT)) and only within this command invocation.
So, if you need destination directory of some target, you should manually write it. Or store it in some target's property and use $<TARGET_PROPERTY:tgt,prop> generator expression. [Note, that if your property reflects relative path, such generator expression cannot be used with install command, because this commands accepts only generator expressions which contain absolute path.]
I'm using get_filename_component in cmake to get the absolute path of a possibly relative path given in a variable.
And I want to do an out-of-tree/out-of-source-build.
It seems to me that get_filename_component is using CMAKE_SOURCE_DIR as reference-path.
Is there a way to change that or to workaround it?
One way I tried is to prefix my potential relative path with ${CMAKE_BINARY_DIR} but that stops working of the path given is not relative.
Assuming your relative path is always relative to CMAKE_BINARY_DIR, then you can handle this pretty easily using if(IS_ABSOLUTE ...):
if(NOT IS_ABSOLUTE ${MyPath})
set(MyAbsPath ${CMAKE_BINARY_DIR}/${MyPath})
endif()
If the subject file or dir exists at CMake run time, then you can always do a find_file call, passing the possible NAMES and PATHS. If the file exists and is found, the resulting variable will hold the full path to the file.
Or you can use the if(EXISTS ...) signature of if to check for the existence or not of the given file.
One specifies find_library(<var> name PATHS path1..pathn)
My question is how does find_library() match name to the library file (on Windows and Linux)?
For example, I am unable to have find_library() identify the MagicK and MagicK++ DLL files in the provided Windows binary installation of GraphicsMagicK:
The files is: CORE_RL_magick_.dll
Searching for the queries: magick or CORE_RL_magick does not work.
You might want to take a look at this documentation links:
http://www.cmake.org/cmake/help/v2.8.10/cmake.html#command:find_library
http://www.cmake.org/cmake/help/v2.8.10/cmake.html#variable:CMAKE_FIND_LIBRARY_PREFIXES
http://www.cmake.org/cmake/help/v2.8.10/cmake.html#variable:CMAKE_FIND_LIBRARY_SUFFIXES
find_library may accept one or more library names. Those names get the value of CMAKE_FIND_LIBRARY_PREFIXES prepended and CMAKE_FIND_LIBRARY_SUFFIXES
appended. This two variables should be set for each OS depending on how the librares are prefixed or suffixed there.
In your case I'd write for Windows
SET(CMAKE_FIND_LIBRARY_PREFIXES "")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".dll")
and for Linux
SET(CMAKE_FIND_LIBRARY_PREFIXES "lib")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a")
and then write
find_library(
magick
CORE_RL_magick_ (or NAMES if there are multiple names for the same library on different systems)
PATHS
path1
path2
...
(other options that are specified in documentation and would be usefull to you)
)
EDIT:
CMAKE_FIND_LIBRARY_PREFIXES and CMAKE_FIND_LIBRARY_SUFIXES are set automatically by project() command so calling it first and find_library() after that point is a better solution than setting the variables manually.
Why not use find_file() instead of find_library() if you want to find a .dll.
I have put these two lines in my Findglm.cmake file to point to the headers for this header library.
find_path(glm_INCLUDE_DIR NAMES glm.hpp matrix_transform.hpp type_ptr.hpp PATHS
${CMAKE_SOURCE_DIR}/libs/glm-0.9.3.2/glm ${CMAKE_SOURCE_DIR}/libs/glm-0.9.3.2/glm/gtc
${CMAKE_SOURCE_DIR}/libs/glm-0.9.3.2/glm/gtx ${CMAKE_SOURCE_DIR}/libs/glm-0.9.3.2glm/core)
set(glm_INCLUDE_DIRS ${glm_INCLUDE_DIR})
However when I generate my Xcode project it says that it cannot locate matrix_transform.hpp and type_ptr.hpp
I have played around with this some more it appears to only find the first argument I am wondering if I am using find path wrong ?
I am using cmake 2.8.8 darwinports.
The find_path() command returns single directory. In your case, it's the first dir, which contains the first file.
If this glm will be always located in your source dir, it would be sufficient to do
include_directories(${CMAKE_SOURCE_DIR}/libs/glm-0.9.3.2/glm
${CMAKE_SOURCE_DIR}/libs/glm-0.9.3.2/glm/gtc
${CMAKE_SOURCE_DIR}/libs/glm-0.9.3.2/glm/gtx
${CMAKE_SOURCE_DIR}/libs/glm-0.9.3.2/glm/core)
The find_path() is used to determine dir somewhere outside of your project.