How to get CMake variable of package in shellscript - shell

I want to find the Qt5WaylandClient_PRIVATE_INCLUDE_DIRS variable which is set by the Qt5WaylandClient package. How can I get it from the shell (dash)? Something like this:
cmake -find_package(Qt5WaylandClient) -get_variable Qt5WaylandClient_PRIVATE_INCLUDE_DIRS
or
cmake -file path/to/my/CMakeLists.txt -get_variable Qt5WaylandClient_PRIVATE_INCLUDE_DIRS

CMake does have a --find-package command line option, but it is not well supported, nor well-documented. There is an answer describing its functionality here, but that's probably not what you're looking for.
Initially, it appears you could just run cmake in script mode, using -P, on a CMake file containing your find_package(Qt5WaylandCleint) command and print its variables to the console.
cmake -P MyFindQt5WaylandClient.cmake
However, running find_package() outside the confines of a CMake project does not work. It yields several errors because CMake doesn't know anything about the system or your target language. So, you must create a minimal CMake project, then run find_package(). Something like this CMakeLists.txt file should work:
cmake_minimum_required(VERSION 3.16)
project(MyProj)
find_package(Qt5WaylandClient REQUIRED)
# Print the desired variable.
message("${Qt5WaylandClient_PRIVATE_INCLUDE_DIRS}")
You can then run cmake from the command line, and this will print the Qt5WaylandClient_PRIVATE_INCLUDE_DIRS variable to the console. You can use the -S and -B command line options to specify the CMake source and binary directories, respectively.
cmake -S . -B build

Related

Is there a default way to have cmake run make with an appropriate -jX argument?

If I have a cmake build tree configured with the -G"Unix Makefiles" option, I understand that I can run
cmake --build . -- -j10
to pass the -j10 option to make but is there a way to tell cmake --build to do this by default (probably when I run the initial cmake)? I'd like to avoid having to write shell scripts that call cmake --build with arguments that depend on the generator.
Right now I'm looking at a bunch of scripts that figure out arguments to cmake, and they hardcoded calls to make -j$NCPUS; I'd like to improve the scripts to make them generator-agnostic, but would really rather not have a bunch of code that looks like if GENERATOR == Unix Makefiles; then DO A THING else DO SOMETHING ELSE.
I did find https://blog.kitware.com/cmake-building-with-all-your-cores/, but that just talks about how to hand-code the flags for each generator.

Cmake doesn't correctly parse whitespace in command line parameter with shell script on windows

I'm trying to run a shell script, which executes a cmake command. It runs on windows on the git-bash.
My run.sh code looks like this:
CMAKE_GENERATOR="'Unix Makefiles'"
performStrict cmake -G "${CMAKE_GENERATOR}" /path/to/dir/
And delivers the following output:
cmake -G 'Unix Makefiles' /path/to/dir/
CMake Error: Could not create named generator 'Unix
I also tried it with (escaped) double quotes. Unfortunately, it gives the same result. Also with many other possible combinations.

Make CMake use gccfilter

GCCFilter is a neat perl script that allows to color the output of GCC and thus makes debugging much more fun and, more important, faster.
You can use GCCFilter with a CMake generated Makefile by calling
gccfilter -a -c make
However, this approach has some drawbacks: Delayed output of CMake status infos, no color in the CMake commands are the most obvious.
The question: Is there a way to write some CMake module that searches for gccfilter if the compiler is gcc, checks if, say COLOR_CXX is set (rather easy up to here) and then tells CMake to replace all calls to gcc by gccfilter -a -c gcc.
CMake offers the variable CMAKE_CXX_COMPILER, but changing this one will disallow CMake to find correct include paths and the like. Is there some variable we may change after the project() command that is prefixed before each call to gcc?
You can make CMake use gccfilter by pointing the RULE_LAUNCH_COMPILE property to a wrapper script which invokes gccfilter with the desired options.
Create an executable shell script named gccfilter_wrap in the outermost CMake project directory with the following contents:
#!/bin/sh
exec gccfilter -a -c "$#"
Be sure to set the file's executable bit. Then in your CMakeLists.txt, set the RULE_LAUNCH_COMPILE directory property before adding targets:
project (HelloWorld)
set_directory_properties(PROPERTIES RULE_LAUNCH_COMPILE
"${PROJECT_SOURCE_DIR}/gccfilter_wrap")
add_executable(HelloWorld HelloWorld.cpp)
The generated makefile rules will then prefix each compiler invocation with the gccfilter_wrap script. Alternatively the RULE_LAUNCH_COMPILE property can also be set as a target property or as global property.
The RULE_LAUNCH_COMPILE property only works for Makefile-based CMake generators.
Edit by Thilo
This is how I finally solved the problem - basically a rephrased version of this solution:
# GCCFilter, if appliciable
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCPP)
option(COLOR_GCC "Use GCCFilter to color compiler output messages" ON)
set(COLOR_GCC_OPTIONS "-c -r -w" CACHE STRING "Arguments that are passed to gccfilter when output coloring is switchend on. Defaults to -c -r -w.")
if(COLOR_GCC)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${PROJECT_SOURCE_DIR}/cmake/gccfilter ${COLOR_GCC_OPTIONS}")
endif()
endif()

How do I configure CMake to make the VS solution use a specific build commandline?

I am trying to set up CMake to generate a MSVC (2010) solution for our project, and need to configure the projects so that they use our specific build system rather than compiling using the default command line.
Here's what the project file looks like for VS2008 (which we generate using another script that I'd like to get away from):
<Tool
Name="VCNMakeTool"
BuildCommandLine="../bam.bat -j %%NUMBER_OF_PROCESSORS%%"
ReBuildCommandLine="../bam.bat -j %%NUMBER_OF_PROCESSORS%% -c && ../bam.bat -j %%NUMBER_OF_PROCESSORS%%"
CleanCommandLine="../bam.bat -j %%NUMBER_OF_PROCESSORS%% -c "
Output="..\..\..\common\win32\container.exe"
PreprocessorDefinitions=""
IncludeSearchPath=""
ForcedIncludes=""
AssemblySearchPath=""
ForcedUsingAssemblies=""
CompileAsManaged=""
/>
It's basically the three CommandLine settings I'd like to be able to specify from my cmake config.
I've found the build_command command in the documentation but from the description it sounds like it does sort of the opposite of what I want, i.e. writes the command line it'll generate to a variable rather than take a string and set the command line to that.
Something that seems a bit related is the cross-compile feature in CMake but I'm sure if that is a good way to do this.
Basically I just want VS to run a batch file when I do a build and then parse the results back to get nice error messages etc.
It looks to me like what you want is simply a "custom command" in CMake parlance.
Something like:
set(custom_exe "${CMAKE_CURRENT_BINARY_DIR}/common/win32/container.exe")
add_custom_command(OUTPUT ${custom_exe}
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bam.bat -j $ENV{NUMBER_OF_PROCESSORS}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bam.bat
)
add_custom_target(bam ALL DEPENDS ${custom_exe})
Maybe you need to write your own CMake Toolchain. You can see examples of toolchains in CMAKE_ROOT/share/Modules/Platform, or in CMake documentation, but i'm not sure whether cmake can generate MSVC solution for custom compiler.

How to print result of shell script in CMake?

If I want to check currently exported environment variables, I do this in shell.
export
In CMake, I do this to print something.
MESSAGE ("This is message.")
How can I print former one with CMake?
I know that CMake is stand for cross-platform building, anyway when debugging something I need to check raw values. So I need this.
If you want to know the value of a specific variable, you can use $ENV{varname}:
message(STATUS $ENV{PATH})
If you want to see all variables, you probably need to resort to invoking an external command such as env (on Unix) or set (on Windows):
# Windows
execute_process(COMMAND cmd /c set OUTPUT_VARIABLE output)
message(${output})
I don't know how to get cmake to show output to a console, but if you don't mind just getting it out of a file later, you can add:
env > /tmp/environment
in the appropriate place, and then read the /tmp/environment file later.

Resources