I have been given some source code, along with a CMakeLists.txt file, and told to run cmake by:
cmake ../src -DOPEN_NI_ROOT=/home/karnivaurus/OpenNI
I have also noticed that there is a file called FindOpenNI.cmake, which I believe is used when find_package(OpenNI) is called by cmake.
Therefore, I am guessing that OPEN_NI_ROOT is some kind of variable that is used by cmake for the remainder of setup.
However, I have tried inserting the line set(OPEN_NI_ROOT "/home/karnivaurus/OpenNI") into my CMakeLists.txt file, in an attempt to avoid the need to add it as an argument at the command line. But this does not seem to do the same thing.
Can somebody please explain how these two variable types are different?
The file FindOpenNI.cmake is open source and can be found at:
https://github.com/victorprad/InfiniTAM/blob/master/InfiniTAM/cmake/FindOpenNI.cmake
The issue is this line in FindOpenNI.cmake (link):
set(OPEN_NI_ROOT "/usr/local" CACHE FILEPATH "Root directory of OpenNI2")
This will set OPEN_NI_ROOT unless it's already in the cache. A simple call to:
set(OPEN_NI_ROOT "/home/karnivaurus/OpenNI")
does not set the variable in the cache, so it will be overridden when the line in FindOpenNI.cmake is hit. Using the command line form of setting the variable will set it in the cache, which is why it works just fine.
The easiest way to avoid having to set the command line option is to set the cache explicitly in your own CMakeLists.txt:
set(OPEN_NI_ROOT "/home/karnivaurus/OpenNI" CACHE FILEPATH "Root directory of OpenNI2")
If you're working from a dirty build directory, it's likely this cache variable already exists, so this line would have no effect. In that case, either work from a clean build directory, or set the FORCE option:
set(OPEN_NI_ROOT "/home/karnivaurus/OpenNI" CACHE FILEPATH "Root directory of OpenNI2" FORCE)
This will write over the cached value. Note that this would prevent you from setting the option in the command line in the future, which is why this method isn't preferred. You can find some more information about the mechanics of this here.
Related
I am using a variable that I want the user to be able to pass using the command line. However, the variable is not overridden as I was expecting. The reference doc I am using is Cmake Cache
My CMakeLists.txt looks like this
cmake_minimum_required(VERSION 3.23.0)
project(design_principles)
set(PRINCIPLE "solid/single_responsibility" CACHE STRING "Enter the principle to be run" FORCE)
message(${PRINCIPLE})
add_executable(
${PROJECT_NAME}
${PRINCIPLE}.cpp
)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)
The command I am passing through the command line is
cmake -S . -B build -DPRINCIPLE=temp
However, it appears that the build is always using the default value from CMakeLists.txt
From the documentation:
Since cache entries are meant to provide user-settable values this does not overwrite existing cache entries by default. Use the FORCE option to overwrite existing entries. [...] If the cache entry does not exist prior to the call or the FORCE option is given then the cache entry will be set to the given value.
The problem is clear: since you have written FORCE, the set() command will always overwrite the cache entry. The solution is to simply get rid of FORCE:
set(PRINCIPLE "solid/single_responsibility"
CACHE STRING "Enter the principle to be run")
want to suppress all error checks in some file. My command line command is
cppcheck --enable=all -j 4 --output-file=out.txt --project=solution.sln --suppress=*:file.cpp
But I got errors from file.cpp in my output file. I used to have quite similar(as far as I recall) command line before and it suppress all checks in the file, but ,u some reason now it doesn't work now. Is my command line wrong?
I know can use suppression file, but I prefer command line parameter and also want to figure out what am I doing wrong.
The suppression needs to match the file path as shown in the result.
If you specify a relative folder/file to check that is straight forward and you can just use the structure from your current folder.
But if you are checking with --project or an absolute path you need to specify -rp (as in "root path") to tell Cppcheck where to base the file paths from. In your case just adding -rp=. should fix the issue - at least it will change the paths in the result from absolute ones to relative ones which are the ones you have to use in your suppression.
I have a CMakeLists.txt.
I use it for generating a makefile with ccmake.
Then upon make, my sources are compiled ok.
At link time, the command line produced is essentially
/opt/rh/devtoolset-6/root/usr/bin/c++ myprog.cc.o -o myprog -Ldir3 -L/opt/rh/devtoolset-3/root/usr/lib/gcc/x86_64-redhat-linux/4.9.2 ... -Wl,-rpath,dir4:dir5:/opt/rh/devtoolset-3/root/usr/lib/gcc/x86_64-redhat-linux/4.9.2 ...
The two spots specifying the search path
/opt/rh/devtoolset-3/root/usr/lib/gcc/x86_64-redhat-linux/4.9.2
should actually point to
/opt/rh/devtoolset-6/root/usr/lib/gcc/x86_64-redhat-linux/6.2.1
How can I fix this?
I have devtoolset-3 in my system, but I do not know where this search path is set, or how to change it.
I actually expected that to take place automatically after executing
scl-devtoolset-6
(in my .bashrc), the same way the correct version /opt/rh/devtoolset-6/root/usr/bin/c++ is detected without me doing anything else.
Of course, I get many linking time errors due to version mismatches.
The only place where I see the search path set is in line
link_directories(${LIBDIR_MY})
in CMakeLists.txt, and LIBDIR_MY points to dir3, which is correctly added in the linking command line.
But I found no place where .../devtoolset-3/... is added.
Possible origins of -L:
link_directories in CMakeLists.txt: checked.
target_link_libraries: Where? What is the expected file name pattern to look for?
link_libraries: Where? What is the expected file name pattern to look for?
CMAKE_LIBRARY_PATH: Checked. It is not set.
A find_package command: See below
Somewhere else?
This How do I add a library path in cmake? does not add to my question.
Update 1:
There was in fact a find_package(mylib) (actually, with a different name) in CMakeLists.txt.
Going to the dir of mylib and issuing find . -name “*” -type f -exec grep /opt/rh/devtoolset-3 {} \; there were two files that matched:
build/CMakeCache.txt:
two occurrences of devtoolset-3
PETSC_LIBRARIES:STRING=...devtoolset-3...
FIND_PACKAGE_MESSAGE_DETAILS_PETSc:INTERNAL=[...devtoolset-3...][YES][v()]
It appears to me that this stems from file CMake/cmake-modules/FindPETSc.cmake (possibly invoked by line find_package (PETSc REQUIRED) in CMakeLists.txt), which has a line
set (PETSC_LIBRARIES ${PETSC_LIBRARIES_ALL} CACHE STRING "PETSc libraries" FORCE)
and many prior lines
set (PETSC_LIBRARIES_<various terms> ...)
Notes:
I do not know where in that file devtoolset-3 is first detected and set.
build/include/summit/mylibConfig.cmake.
I still could not track down what made devtoolset-3 appear here.
I found the culprit.
As hinted at in Update 1 of the OP, the sequence is the following:
Line
find_package (PETSc REQUIRED) in file (1)
CMakeLists.txt forced processing file (2)
CMake/cmake-modules/FindPETSc.cmake.
Line*1
petsc_get_variable (PETSC_EXTERNAL_LIB_BASIC petsc_libs_external) in file (2)
CMake/cmake-modules/FindPETSc.cmake sets a local cmake variable
petsc_libs_external from the value of the variable
PETSC_EXTERNAL_LIB_BASIC read from file (3)
~/petsc-3.8.2/lib/petsc/conf/petscvariables.
PETSC_EXTERNAL_LIB_BASIC is not set explicitly in file (3)
~/petsc-3.8.2/lib/petsc/conf/petscvariables. Line
include ~/petsc-3.8.2/arch-linux2-c-debug/lib/petsc/conf/petscvariables forces reading file (4)
~/petsc-3.8.2/arch-linux2-c-debug/lib/petsc/conf/petscvariables.
Line
PETSC_EXTERNAL_LIB_BASIC = ... -Wl,-rpath,/opt/rh/devtoolset-3/root/usr/lib/gcc/x86_64-redhat-linux/4.9.2 -L/opt/rh/devtoolset-3/root/usr/lib/gcc/x86_64-redhat-linux/4.9.2 -Wl,-rpath,/opt/rh/devtoolset-3/root/usr/lib64 -L/opt/rh/devtoolset-3/root/usr/lib64 -Wl,-rpath,/opt/rh/devtoolset-3/root/usr/lib -L/opt/rh/devtoolset-3/root/usr/lib ... in file (4)
/home/sserebrinsky/petsc-3.8.2/arch-linux2-c-debug/lib/petsc/conf/petscvariables brings the "undesired" directories into the executed command line.
*1 (petsc_get_variable is a macro defined in FindPETSc.cmake)
I am using CMake add_custom_command In a Util.cmake script to download a couple of files that will later be used in the build process. These files however may change and I would like to add a way to check the hash value of the local file against a provided value (within CMake) to decide if the file needs to be re-downloaded.
Currently, once the file has been downloaded, CMake will not consider re-downloading it, because the file already exists locally.
In the future, I want to provide a MD5 / SHA256 checksum of that file and make sure the local file is the corect one.
Here is what I am trying to do (this is just an concept example):
add_custom_command( OUTPUT ./file.dat
COMMAND wget ${FILE_PATH}
)
if (opt_HASH)
add_custom_command(OUTPUT ${local_HASH}
COMMAND local_HASH=$(sha256sum ./file.dat)
DEPENDS ./file.dat
)
if (NOT ${opt_HASH} STREQUAL ${local_HASH})
# throw ERROR
endif()
endif()
As you can see I only want to detect a mismatch right now and don't even want to auto-download the changed file. The opt_HASH is obviously provided through CMake, but what is important is that this call needs to depend on the file already being downloaded and I seem to be able to do that with a more simpler call to FILE().
PS: If it's somehow easier, I could also use MD5 over SHA256.
cmakes FILE command supports hashing:
https://cmake.org/cmake/help/v3.8/command/file.html
file(SHA256 ./file.dat CHECKSUM_VARIABLE)
should put the hash into the CHECKSUM_VARIABLE
The usage of add_custom_target could be one solution. By default it will be executed always. The following should work on linux:
add_custom_target(UpdateExternalFiles
COMMAND "sha256sum -c file.dat.checksum ./file.dat || wget ${FILE_PATH}"
COMMAND "sha256sum ./file.dat >> file.dat.checksum"
)
First line verifies the checksum and loads the file on differences. The second line updates the checksum.
Note: This snipped assume that file.dat.checksum will be created with the second command.
I compiled my program with intel C++ compiler for windows (from Intel Composer 2011), and got an error message that libmmdd.lib cannot be found. I googled this problem, and some people said that I have to reinstall my compiler, and I did; however, that didn't resolve the problem, so I started looking in the intel compiler directory, and found that this file (and other required libraries as well) are located at
%CompilerDirectory%\compiler\lib\ia32
It doesn't make sense to write in the make file the whole absolute path of the libraries, so I started searching, and I could only find that %mklroot% points to the math kernel directory. And even with a -L%mklroot%/../compiler/lib/ia32 approach for linking I couldn't link to the libraries correctly, so eventually I did a lame move to solve the problem, which is, I copied every file the linker asks for to the source directory, and so was the problem temporarily solved.
Since this way of solving the problem isn't the best one, I wonder if there's a way to link to those libraries without having to copy the files. It's strange because the compiler should find its own libraries alone, but... I don't know...!
Any ideas? is there something like, %compilerroot%, that points to the compiler directory and that I could put in my makefile (or actually my qmake, since I'm using Qt).
Thanks for any efforts :-)
Instead of using %mklroot% try $$(mklroot) or $(mklroot).
You can find the explanation here:
Variables can be used to store the contents of environment variables.
These can be evaluated at the time that qmake is run, or included in
the generated Makefile for evaluation when the project is built.
To obtain the contents of an environment value when qmakeis run, use
the $$(...) operator:
DESTDIR = $$(PWD)
message(The project will be installed in $$DESTDIR)
In the above assignment, the value of the PWD environment variable is
read when the project file is processed.
To obtain the contents of an environment value at the time when the
generated Makefile is processed, use the $(...) operator:
DESTDIR = $$(PWD)
message(The project will be installed in $$DESTDIR)
DESTDIR = $(PWD)
message(The project will be installed in the value of PWD)
message(when the Makefile is processed.)
In the above assignment, the value of PWD is read immediately when the
project file is processed, but $(PWD) is assigned to DESTDIR in the
generated Makefile. This makes the build process more flexible as long
as the environment variable is set correctly when the Makefile is
processed.
EDIT:
It is strange that neither $$(mklroot) nor $(mklroot) gave you the result you would expect. I did a simple test to verify what I wrote above:
Opened a Command Prompt
Created a new environment variable 'mklroot' with a test value: set mklroot=C:\intel_libs
Verified the result of the previos step: echo %mklroot%. I got C:\intel_libs
Placed your 3 qmake functions at the end of my .pro file:
warning($(%MKLROOT%))
warning($(MKLROOT))
warning($$(MKLROOT))
Ran qmake: qmake. The result:
Project WARNING:
Project WARNING: c:\intel_libs
Project WARNING: c:\intel_libs
As you can see the 2nd and the 3rd warning() displayed the string I set to the environment variable.