I using CMake 3.5.1 on Debian 7 for my project. Here is the code in my CMakeLists.txt
find_package(Qt5 REQUIRED COMPONENTS Core)
message(STATUS ${Qt5Core_INCLUDE_DIRS})
But the print out of ${Qt5Core_INCLUDE_DIRS} is
/usr/include/x86_64-linux-gnu/qt5//usr/include/x86_64-linux-gnu/qt5/QtCore/usr/lib/x86_64-linux-gnu/qt5//mkspecs/linux-g++-64 which has no space between the paths.
What's wrong with CMake or is anything wrong in my CMakeLists.txt? How can I fix this?
thank you!
Qt5Core_INCLUDE_DIRS variable is a list, that is a string delimited with ;. When printing such strings, CMake omits delimiter and concatenates elements.
Use list and foreach commands to work with list elements.
Related
Stumbled upon something like this in a cmake file and couldn't find the syntax explanation neither in cmake documentation, nor on the Internet.
SET(%MY_LIB_TYPE% ON)
The same line is defined in a .cmake and in a similarly named .cmake.in files, and MY_LIB_NAME does not appear anywhere else.
What does %string% syntax do?
In CMake, nothing. It looks like a template placeholder for something that's generating CMake files. I believe this is the most likely option.
Otherwise, % is technically an allowable variable name character in CMake, though you have to indirect through another variable to read it.
$ cat test.cmake
cmake_minimum_required(VERSION 3.20)
set(%FOO% bar)
set(var "%FOO%")
message("${${var}}")
$ cmake -P test.cmake
bar
I have defined the following macro in CMake (version 3.10):
macro(configureQt4 requiredVersion selectedPackages)
message(STATUS "selectedPackages: ${selectedPackages}")
find_package(Qt4 ${requiredVersion} COMPONENTS ${selectedPackages} REQUIRED )
endmacro()
Now, when I tried to call the macro in the following way, I get an error:
set(SelectedQt4Packages "QtCore QtNetwork")
configureQt4( 4.8 ${SelectedQt4Packages})
The error reported is:
CMake Error at /usr/share/cmake-3.10/Modules/FindPackageHandleStandardArgs.cmake:137 (message):
Could NOT find Qt4 (missing: QT_QTCORE QTNETWORK_INCLUDE_DIR QT_QTCORE
QTNETWORK_LIBRARY) (found suitable version "4.8.7", minimum required is
"4.8")
If I call find_package() in the following way inside the macro, it works!
find_package(Qt4 ${requiredVersion} COMPONENTS QtCore QtNetwork REQUIRED )
But I need to use it by setting a variable as discussed earlier. How can I resolve this issue?
If you want to set a list variable in CMake, you can achieve this by excluding the quotes:
set(SelectedQt4Packages QtCore QtNetwork)
Using quotes like this "QtCore QtNetwork" simply creates a string with a space between the two component names, which is likely not what you intend.
Now, you can pass the SelectedQt4Packages list variable to your macro, but be sure to surround it with quotes (as suggested in this answer):
set(SelectedQt4Packages QtCore QtNetwork)
configureQt4( 4.8 "${SelectedQt4Packages}")
This is because CMake expects a list of components. That is, a string where each item is separated by a ;. If you instead do set(SelectedQt4Packages "QtCore;QtNetwork") and change the call to configureQt4( 4.8 "${SelectedQt4Packages}") (note the double quotes), it should work as expected.
Edit: A cleaner solution would be to simply convert the argument to a list inside the macro:
# Now we can set selectedPackages to either "QtCore QtNetwork" or "QtCore;QtNetwork", both will work.
macro(configureQt4 requiredVersion selectedPackages)
message(STATUS "selectedPackages: ${selectedPackages}")
string(REPLACE " " ";" _selectedQtPackages ${selectedPackages})
find_package(Qt4 ${requiredVersion} COMPONENTS ${_selectedQtPackages} REQUIRED )
endmacro()
Disclaimer: I'm aware of this question. However, The OP's needs are different to mine: what he actually wants is to port an app to Linux and therefore the answers go in that line, not answering what I want to know: the reasons of the error.
I'm trying to create a dropdown list in CMake GUI following the instructions in here and here
So I have this very simple CMakeLists.txt:
cmake_minimum_required(VERSION 3.6)
project(datasetprograms)
set(CMAKE_CXX_STANDARD 11)
#LINES TO MAKE THE GUI DROP-DOWN:
set(TARGET_ARCHITECTURE “arm” CACHE STRING “Architecture to compile to”)
set_property(CACHE TARGET_ARCHITECTURE PROPERTY STRINGS arm x86)
#Add subdirectories for each project
add_subdirectory(helloworld)
Basically I just copied and pasted, following the instructions. However, instead of having a nice drop-down in the CMake GUI, I got the following error:
CMake Error at CMakeLists.txt:9 (set_property): set_property could
not find CACHE variable TARGET_ARCHITECTURE. Perhaps it has not yet
been created
Question: What I'm doing wrong?
You may check value of variable TARGET_ARCHITECTURE using message() and you will found CACHE is a part of that value.
This is because you use in set() command double quotes which are not common ones (") but language-specific (“). So CMake treats set() command as not CACHE'd one. That is a reason of the error message.
I can pass defined variable for cmake like below(for example when I want to set PYTHON_INCLUDE_PATH=dir1).
cmake -DPYTHON_INCLUDE_PATH=dir1 ..
But what if I want to set multiple paths for this PYTHON_INCLUDE_PATH? I tried
cmake -DPYTHON_INCLUDE_PATH='dir1 dir2 dir3'
or should it be
cmake -DPYTHON_INCLUDE_PATH='dir1:dir2:dir3' (or , instead of :)
But I'm not sure it's valid. (see some other error so I am not sure yet if it's correct or not.)
I saw I can also set these defines in .cmake file like set(VARIABLE,VALUE) like below.
set(OpenCV_CUDA_VERSION 7.5)
Then what's the corresponding syntax for this set(..) form when the variable has multiple elements?
use the following syntax:
cmake -DLIST_VAR="one;two;three" ...
you can play w/ the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
foreach(v IN LISTS LIST_VAR)
message(STATUS "${v}")
endforeach()
I wonder if there is a better solution to my problem. I am working on a platform independent software project and want to add python-based unittests to cmake. The issue that I encountered now is that when configuring the ctest tests and setting up the correct PYTHONPATH environment variable for running my test, I end up with a lot of boilerplate code for each test:
add_test(my_awesome_test ${PYTHON_EXECUTABLE} my_awesome_test.py)
if("${CMAKE_HOST_SYSTEM}" MATCHES ".*Windows.*")
set_tests_properties(my_awesome_test PROPERTIES ENVIRONMENT "PYTHONPATH=somepath\;anotherpath")
else() # e.g. Linux
set_tests_properties(my_awesome_test PROPERTIES ENVIRONMENT "PYTHONPATH=somepath:anotherpath")
endif()
# more tests like this after this...
The problem here is the branching, that is required only because of the platform dependent list separators.
Is there some neater way to accomplish this?
Is there a constant which specifies the platform separator or a function that allows me to construct these lists?
If there is no "proper" answer, I also wanted to share my obvious, but not-so-nice solution:
if("${CMAKE_HOST_SYSTEM}" MATCHES ".*Windows.*")
set(SEP "\\;")
else() # e.g. Linux
set(SEP ":")
endif()
add_test(my_awesome_test ${PYTHON_EXECUTABLE} my_awesome_test.py)
set_tests_properties(my_awesome_test PROPERTIES ENVIRONMENT "PYTHONPATH=somepath${SEP}anotherpath")
# more tests like this after this...
On Windows the ";" must be double escaped because otherwise it it is substituted later in the add_test line as a single ";" again, which is then in turn interpreted as the cmake-list separator leading to wrong results. However, having cmake report which character should be used as list separator would still be nicer...
Unfortunately file(TO_NATIVE_PATH ... does not convert ; to : on Unix platforms. I think the easiest way is therefore something like this:
set(PATH "/usr/bin" "/bin")
if (UNIX)
string(REPLACE ";" ":" PATH "${PATH}")
endif()
This works because CMake lists are really ;-separated strings, so on Windows you can use them for path lists as-is. It won't work for paths containing ; or : but that will trip up 99% of Unix software anyway so I wouldn't worry about it.
You can use the file function as follow:
file(TO_CMAKE_PATH "<path>" <variable>)
file(TO_NATIVE_PATH "<path>" <variable>)
https://cmake.org/cmake/help/v3.9/command/file.html
You may define function/macro which transforms some choosen separator into platform-specific one. E.g., function below transforms CMake list into platform-specific path list:
function(to_path_list var path1)
if("${CMAKE_HOST_SYSTEM}" MATCHES ".*Windows.*")
set(sep "\\;")
else()
set(sep ":")
endif()
set(result "${path1}") # First element doesn't require separator at all...
foreach(path ${ARGN})
set(result "${result}${sep}${path}") # .. but other elements do.
endforeach()
set(${var} "${result}" PARENT_SCOPE)
endfunction()
Usage:
to_path_list(pythonpath "somepath" "anotherpath")
set_tests_properties(my_awesome_test PROPERTIES ENVIRONMENT "PYTHONPATH=${pythonpath}")