I try to use cmake determine whether exist inttypes.h header file for generate project of visual c++ 11.
Initially, i wrote the following sentence in CMakeLists.txt
FIND_FILE(HAVE_INTTYPES_H "inttypes.h" DOC "Does the inttypes.h exist?")
Unfortunately, the HAVE_INTTYPES_H variable is HAVE_INTTYPES_H-NOTFOUND.
Afterwards, i looked up cmake documentation about find_file, which mentioned the need to some search path. But i can not get the c standard header files in any place in cmake?
Thanks.
Your find_file call is correct. The problem is there's no inttypes.h on Visual Studio. So keep your test the same, but when it's not found include another headers, for instance provided by: http://code.google.com/p/msinttypes/
Something like:
FIND_FILE(HAVE_INTTYPES_H "inttypes.h" DOC "Does the inttypes.h exist?")
if (HAVE_INTTYPES_H)
add_definitions(-DHAVE_INTTYPES_H=1)
endif()
and in your code:
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#else
#include "path/to/inttypes.h"
#endif
Now, to detect headers, you may also want to try using the CheckIncludeFile standard CMake module, it's trying to detect include files using your target compiler instead of searching the file system:
include(CheckIncludeFile)
check_include_file("stdint.h" STDINT_H_FOUND)
if (STDINT_H_FOUND)
add_definitions(-DHAVE_STDINT_H=1)
endif()
Related
I am learning CMake with CMake Tutorial and found something which is not clear for me:
include(CheckSymbolExists)
set(CMAKE_REQUIRED_LIBRARIES "m")
So what is the CheckSymbolExists? Is it a function or a lib?
What's meaning of the "m"? Does it mean a lib name or some flag?
I had tried to read through cmake documents, but I just don't understand.
Please somebody help me to understand these.
First, set(CMAKE_REQUIRED_LIBRARIES "m") includes the math library. You do the same on the command-line like this: gcc test.c -lm which includes the library libm.so/.dll
CheckSymbolExists is a CMake Module which provides more functionality. You can include it with include(CheckSymbolExists)
After this you can use the function check_symbol_exists(...) in CMake to check the availability of symbols in header files.
The exact example from the tutorial:
check_symbol_exists(log "math.h" HAVE_LOG) checks if the header file math.h has a symbol (can be a function, constant or whatever) which is called log. If there is one, the CMake Variable HAVE_LOG is set to 1, otherwise set to 0.
The document said, if my understanding is correct, this module will check if a symbol can be correctly linked when it saw a symbol that is not a enum, type or intrinsic.
So in that snippet, when the first runs of check_symbol_exists didn't define the two cache variable, it will check if it had missed an required lib, and retry.
I have a simple CMakeLists for my shader code which currently just looks like this -
target_sources( JonsEngine
PRIVATE
AmbientPixel.hlsl
AvgLuminance.hlsl
BoxBlurPixel.hlsl
Common.hlsl
Constants.h
DepthReadback.hlsl
DirectionalLightPixel.hlsl
DirectionalLightPCF2X2Pixel.hlsl
DirectionalLightPCF3X3Pixel.hlsl
DirectionalLightPCF5X5Pixel.hlsl
DirectionalLightPCF7X7Pixel.hlsl
FullscreenTriangle.hlsl
FullscreenTriangleTexcoord.hlsl
FXAA.hlsl
FXAAPixel.hlsl
GBufferPixel.hlsl
GBufferVertex.hlsl
GBufferVertexAnimated.hlsl
GBufferVertexStatic.hlsl
OptimizedPCF.hlsl
PointLightPixel.hlsl
SDSMFinalCompute.hlsl
SDSMInitialCompute.hlsl
SimpleColorPixel.hlsl
SimpleTexturePixel.hlsl
SkyboxPixel.hlsl
SkyboxVertex.hlsl
SSAOPixel.hlsl
TerrainDomain.hlsl
TerrainHull.hlsl
TerrainPixel.hlsl
TerrainPixelDebug.hlsl
Tonemapping.hlsl
TransformAnimatedVertex.hlsl
TransformStaticInstancedVertex.hlsl
TransformStaticVertex.hlsl
)
I am trying to add a bunch of compile flags to some of them using like -
set_source_files_properties( AmbientPixel.hlsl PROPERTIES COMPILE_FLAGS "/E\"ps_main\" /ps\"_5_0\"" )
However when I generate the solution via CMake it seems to ignore this when I look at the compile options for that source file. What am I doing wrong?
EDIT: CMake 3.14+
CMake treats HLSL files as source extra, as it is not a first class language in CMake. Others have had your issue as well, which prompted CMake to add the VS_SHADER_FLAGS option.
Try something like this instead:
add_executable(JonsEngine)
# Set HLSL source file properties with VS_SHADER_FLAGS.
set_source_files_properties( AmbientPixel.hlsl PROPERTIES VS_SHADER_FLAGS "/E\"ps_main\" /ps\"_5_0\"")
# Associate these source extras with the executable defined above.
target_sources(JonsEngine PRIVATE
AmbientPixel.hlsl
AvgLuminance.hlsl
#
# ... other code files here ...
#
)
There are several other shader options CMake created for the Visual Studio generator, such as VS_SHADER_TYPE and VS_SHADER_ENTRYPOINT which provide additional build information to the shader compiler.
Note: This is my first time using CMake. I don't know much about it, so I'm just posting a bunch of information to see if anyone can see my problem.
I would like the ability to automatically determine which c++11 flag is appropriate, given my compiler. There are many examples of this line. Here is my CMakeLists.txt following such an example:
cmake_minimum_required (VERSION 2.8)
#Add the c++11 flag, whatever it is
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG(-std=c++0x COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
project(AnalyzeGames)
set(AnalyzeGames_SRCS AnalyzeGames.cpp)
add_executable(AnalyzeGames ${AnalyzeGames_SRCS})
Here is my cmake output when trying to use this file: http://pastebin.com/3AUwqffD
Here is CMakeError.log: http://pastebin.com/EbNKvGt8
Here is CMakeOutput.log: http://pastebin.com/kVJ0enJC
echo $CC: /usr/bin/gcc
echo $CXX: /usr/bin/g++
I can compile a simple test executable with g++ using either flag manually.
cmake --version: cmake version 2.8.12.2
For some reason CMake is not recognizing that my compiler does support both of those flags.
The cmake output tells you that it does not recognize the '.cxx' extension because it doesn't know that your project is a C++ project. To fix this, you should enable C++ in the project command. Try to change the following line:
project(AnalyzeGames)
to:
project(AnalyzeGames CXX)
and then move it to the 2nd line of the CMakeLists.txt, right under cmake_minimum_required. The configuration should work as expected after this.
TLDR
Compiler checks are only performed in the variable passed is not previously defined, which includes in the cache from previous failed attempts. Use unset(my_var CACHE) to force checking to always occur, or just be aware of this behaviour and clear the cache manually when needed.
Detail
I too had this problem (with cmake 2.8.12.2) and I had to turn on trace output, and step through the code to get a similar toy build to work I had make sure the variables I used (COMPILER_SUPPORTS_CXX11_*) in these calls:
CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG(-std=c++0x COMPILER_SUPPORTS_CXX0X)
Were set such that they named themselves:
set(COMPILER_SUPPORTS_CXX11 "COMPILER_SUPPORTS_CXX11")
The other posters solution didn't work for me, it mainly just seemed to limit the detecting of compilers to just CXX and ignored the C compiler.
The issue appears to be with this line of code in the cmake module:
if("${VAR}" MATCHES "^${VAR}$")
Which in the trace output is:
/usr/share/cmake/Modules/CheckCXXSourceCompiles.cmake(30): if(COMPILER_SUPPORTS_CXX0X MATCHES ^COMPILER_SUPPORTS_CXX0X$ )
It looks as if the expression on the left of the MATCHES is replaced with the variables value, but the expression on the right is assumed to be plain text.
If the MATCH fails then the main part of the macro is skipped and according the to the log the check fails.
Looking at later versions of this macro online it looks as if this line has changed to only perform the compile check if the variable is undefined.
It as at this point that I realise that this is the intent / hack of the original code; if the X is undefined then "X" MATCHES "^X$" will be true, but then the compile check can be performed, fail for some other reason and then never be performed again.
So the solution is either force unset of variable in cache before calling the macro using:
unset(COMPILER_SUPPORTS_CXX0X CACHE)
Or clear the cache manually and be prepared for this behaviour.
I need link my program against Kerberos authentication library (gssapi_krb5) with the corresponding headers gssapi/gssapi.h and gssapi/gssapi_krb5.h included in the source file.
Currently, the compilation will continue if headers are absent and stop with a compile time error saying header files not found.
What I want to implement in the cmake file is to check the existence of the header file and stop compiling if not found.
I add the following code into my CMakeList.txt file.
INCLUDE(CheckIncludeFiles)
CHECK_INCLUDE_FILES(gssapi/gssapi.h;gssapi/gssapi_krb5.h HAVE_KRB_HEADERS)
IF (NOT HAVE_KRB_HEADERS)
RETURN()
ENDIF (NOT HAVE_KRB_HEADERS)
But it still does not act as I expected.
I would like the following lines:
-- Looking for gssapi/gssapi.h - found
-- Looking for gssapi/gssapi_krb5.h - not found
but fail.
Also, the variable HAVE_KRB_HEADERS is empty when output with message macro.
Compile continues until the error described above occurs.
I read somewhere on the Web, this may be because CMake cache.
I'm very new to CMake and not quite clear with that concept.
My CMake version is 2.6.
How could I make this code work? Thank you!
I can't say I'm a huge fan of CheckIncludeFiles because of its difficulty to get right. In principal it's good - it actually creates tiny c files which #include the requested headers and tries to compile them, but it seems to be too easy to get wrong.
I generally prefer just using find_path and/or find_file for this job. This doesn't check the contents of any files found, but usually if you find the required header, its contents are good!
I would use find_path if I needed to know the folder where the header lived. This would usually be because I need to check for other files in the same folder (as in your case), or more commonly because I need to add the folder to an include_directories call.
find_file yields the full path to the file (if found). For headers, normally I don't need the path elsewhere in the CMakeLists - it's just used immediately after the find_file to check the file was actually found.
So, here's how I'd go about checking for "gssapi/gssapi.h" and "gssapi/gssapi_krb5.h"
find_path(GssApiIncludes gssapi.h PATHS <list of folders you'd expect to find it in>)
if(NOT GssApiIncludes)
message(FATAL_ERROR "Can't find folder containing gssapi.h")
endif()
find_file(GssKrb gssapi_krb5.h PATHS ${GssApiIncludes} NO_DEFAULT_PATH)
if(NOT GssKrb)
message(FATAL_ERROR "Can't find gssapi_krb5.h in ${GssApiIncludes}")
endif()
If you do this, then if required you could add
include_directories(${GssApiIncludes})
so that in your source code you can do
#include "gssapi.h"
#include "gssapi_krb5.h"
For anyone who has to work with CHECK_INCLUDE_FILES, the documentation lists a variable called CMAKE_REQUIRED_INCLUDES where you can set additional include paths apart from the default headers.
In a CMake file:
LIST(APPEND CMAKE_REQUIRED_INCLUDES "gssapi")
From the command line:
cmake . --DCMAKE_REQUIRED_INCLUDES="gssapi"
If all else fails, you can set the -I<dir> flag manually. However, this is not recommended as it not portable across compilers.
# note the extra space before `-I`
STRING(APPEND CMAKE_C_FLAGS " -Igssapi")
STRING(APPEND CMAKE_CXX_FLAGS " -Igssapi") # for C++
Also note that C++ headers have a different macro called CheckIncludeFileCXX.
I feel a little stupid right now. After recently converting a few smaller projects to use CMake, I decided to also get rid of a few "Platform_Config.h" files. These files contain a few preprocessing directives like #define USE_NEW_CACHE and control compilation.
How would I 'convert' these defines to be controlled with CMake? Ideally by using these "cache" variables the user can easily edit.
There are two options. You can use the add_definitions method to pass defines as compiler flags: E.g. somewhere in your projects cmakelists.txt:
add_definitions( -DUSE_NEW_CACHE )
CMake will make sure the -D prefix is converted to the right flag for your compiler (/D for msvc and -D for gcc).
Alternatively, check out configure_file. It is more complex, but may be better suited to your original approach with a Platform_Config file.
You can create an input-file, similar to your original Platform_Config.h and add "#cmakedefine" lines to it.
Let's call in Platform_Config.h.in:
// In Platform_Config.h.in
#cmakedefine USE_NEW_CACHE
// end of Platform_Config.h.in
When then running
configure_file( ${CMAKE_SOURCE_DIR}/Platform_Config.h.in ${CMAKE_BINARY_DIR}/common/Platform_Config.h )
it will generate a new Platform_Config file in your build-dir. Those variables in cmake which are also a cmakedefine will be present in the generated file, the other ones will be commented out or undefed.
Of course, you should make sure the actual, generated file is then correctly found when including it in your source files.
option command might provide what you are looking for.
use it with the COMPILE DEFINITIONS property on the target and i think you are done.
To set the property on the target, use the command set target properties
option(DEBUGPRINTS "Prints a lot of debug prints")
target(myProgram ...)
if(DEBUGPRINTS)
set_target_properties(myProgram PROPERTIES COMPILE_DEFINITIONS "DEBUGPRINTS=1")
endif()
edit:
The option i wrote in the example shows up as a checkbox in the CMake GUI.
In case you want to set defines per target: Since 2.8.11 you can use target_compile_definitions.
In earlier versions you probably don't want to use set_target_properties as is, since it overwrites any defines you set previously. Call get_target_property first instead, then merge with previous values. See add_target_definitions here.
Use target_compile_options. Do not quote your define or it not be detected as a define. CMake parses off the /define and adds the actual define to the DefineConstants section of the csproj, if there are quotes it will put the entire quoted string in the AdditionalOptions section of the csproj.
An example from one of my projects that uses generator expressions:
target_compile_options( ${LIBRARY_NAME} PRIVATE
$<${IS_ART_ITERATION_BUILD}:/define:ART_ITERATION_BUILD>
)
An example without generator expressions:
target_compile_options( ${LIBRARY_NAME} PRIVATE
/define:GRAPHICS_VULKAN
)