In CMake I'm doing something like this:
LINK_DIRECTORIES( $ENV{VARNAME}/lib )
However, that will expand the environment variable so that the generated visual studio project will have a hard coded path, e.g:
C:/PathToWhereVarNamePointed/lib
Is there a way to make the above call so that visual studio will end up the below instead?
$(VARNAME)/lib
Because CMake 2.8.1 changed how this value is interpreted (relative vs. absolute), in addition to escaping the dollar and the parens, you need to set the old policy:
CMAKE_POLICY( SET CMP0015 OLD )
LINK_DIRECTORIES(
\$\(VARNAME\)/lib
)
CMAKE_POLICY( SET CMP0015 NEW )
Then it shows up like:
The CMake docs say that LINK_DIRECTORIES is "rarely necessary". Are you sure this is the right way to do it?
Related
I have very complex CMake project. Where variables are often defined like set("${scope}_${variable_name}" value..) or other complex way.
I need to find where a variable is defined, where it obtains a value.
I tried variable_watch at the beginning of the cmake, but that only gives me READ_ACCESS so I guess that setting the variable is not covered in variable_watch mechanics.
I need to find out where that variable is set, but I run out of ideas. Variable watch does not help, search sources fails due to complex variable definitions.
You can add on top of the CMakeLists:
macro(set name)
message(STATUS "defninng ${name}")
_set(${name} ${ARGV})
endmacro()
set(a b)
and print CMAKE_CURRENT_LIST_* variables.
You could do this without modifying the cmake files: Simply use grep (or windows equivalent) in combination with running the cmake configuration with the --trace-expand option.
Using this option for example
message("TGT_TYPE = ${TGT_TYPE}")
could result in console output like
/some/path/CMakeLists.txt(71): message(TGT_TYPE = UTILITY )
TGT_TYPE = UTILITY
so
cmake --trace-expand build_dir | grep -P "[sS][eE][tT]\s*\(\s*VARIABLE_NAME\s"
should provide you with the line containing the logic to set VARIABLE_NAME in the project you've set up in the directory build_dir.
My cmake file contains this statement:
link_directories("C:/path/to/lib")
In the properties of the generated Visual Studio solution I see:
/LIBPATH:"C:/path/to/lib"
/LIBPATH:"C:/path/to/lib/Release"
I am not sure where that second LIBPATH is coming from.
Within the cmake file I would like to print out the LINK_DIRECTORIES property, how would I do that? I have tried various things along the lines of...
cmake_print_properties(DIRECTORIES xxx PROPERTIES LINK_DIRECTORIES)
...but I am not sure what parameters to pass.
Edit OK this worked:
cmake_print_properties(DIRECTORIES . PROPERTIES LINK_DIRECTORIES)
It prints out:
Properties for DIRECTORY .:
..LINK_DIRECTORIES = "C:/path/to/lib"
So where is that second LIBPATH coming from? I don't know whether it is generated by cmake somehow, or added later by Visual Studio.
I am using a cmake generator expression to read a target property
set_tests_properties(
Java-wrapper
PROPERTIES
ENVIRONMENT _JAVA_OPTIONS=-Djava.library.path=$<TARGET_PROPERTY:ktx-jni,LIBRARY_OUTPUT_DIRECTORY>
)
LIBRARY_OUTPUT_DIRECTORY is itself defined using a generator expression
set_target_properties(ktx-jni PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${KTX_BUILD_DIR}/$<CONFIG>
)
During build LIBRARY_OUTPUT_DIRECTORY is expanded correctly and the built library appears in Debug or Release as expected. However in the environment seen by the test $<CONFIG> is not expanded.
Picked up _JAVA_OPTIONS: -Djava.library.path=/Users/mark/Projects/khronos/github/KTX-Software/build/macos/$<CONFIG>
If instead I use
ENVIRONMENT _JAVA_OPTIONS=-Djava.library.path=${KTX_BUILD_DIR}/$<CONFIG>
$<CONFIG> is expanded correctly and the test runs successfully.
How can I get cmake to recursively expand LIBRARY_OUTPUT_DIRECTORY?
I found the solution, use TARGET_GENEX_EVAL, as in the below.
ENVIRONMENT _JAVA_OPTIONS=-Djava.library.path=$<TARGET_GENEX_EVAL:ktx-jni,$<TARGET_PROPERTY:ktx-jni,LIBRARY_OUTPUT_DIRECTORY>>
I missed it before because it is listed under String Transformations not Target Dependent Queries in the cmake documentation.
In my project I need to include different files for different build configurations and thus far I've been unable to find a way to do it via CMake.
My build command looks the following way:
cmake -DCMAKE_CONFIGURATION_TYPES=Debug2017;Debug2018;Debug2019;Release2017;Release2018;Release2019 -G"Visual Studio 14 2015" #and so on
In my CMakeLists.txt I want to have something that looks like:
if ($<$<CONFIG:Debug2017>: )
set (MAYA_DIRECTORY "C:/Program Files/Autodesk/Maya2017" )>
endif()
if ($<$<CONFIG:Debug2018>: )
set (MAYA_DIRECTORY "C:/Program Files/Autodesk/Maya2018" )>
endif()
#and so on; obviously script above don't work. I posted it just as an example of what I want to achieve
variable MAYA_DIRECTORY is used later on to set different other variables that are used for include_directories(…) and link_directories(…) calls.
If there is a way to do this by something other than generator expressions that would also work.
Thanks!
You don't. It is possible for single config generators to use CMAKE_BUILD_TYPE but that strategy fails for for multi-config generators like Visual Studio. This is mixing up what happens at configuration time and build time. The active configuration happens at build time.
Therefore you need a separate MAYA_DIRECTORY for each build config. Then you need to include each Maya into the build (I'm guessing they are external projects or something). Then you need to use a generator expressions to pick which Maya you want to use in the executable.
It would be something like this.
target_include_directories(myApp PRIVATE
$<$<CONFIG:Debug2016>:${MAYA_2016_INCS}>
$<$<CONFIG:Debug2017>:${MAYA_2017_INCS}> )
target_link_libraries(myApp PRIVATE
$<$<CONFIG:Debug2016>:${MAYA_2016_LIBS}>
$<$<CONFIG:Debug2017>:${MAYA_2017_LIBS} )
FYI, If you are creating multiple configuration types you need to seed them properly. That is make sure you create a *_Debug2017 with the debug flags and so on.
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
)