how to make Cmake output relative path? - cmake

In my last deleted question about CMake, I raised a problem about how to make CMake output relative path because vscode's problem panel only
understanding Windows directories or relative paths under workspace.
This won't happen unless some specific situation. If you use vsocde to edit source files in Windows and use WSL as terminal to compile using CMake, you will find vscode cannot work perfectly.
the problem panel will tell you it could not find the error or warning's source code after compilation completes.
gdb could not find source file when debugging.

(1)Solution to the first problem:Add the following code to your outermost CMakeLists.txt:
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_SOURCE_DIR}/custom_output.sh")
The global RULE_LAUNCH_COMPILE property is set to a custom launch script named custom_output.sh which needs to be added to the root of the CMake source tree:
#!/bin/bash
# shell script invoked with the following arguments
# $(CXX) $(CXX_DEFINES) $(CXX_FLAGS) -o OBJECT_FILE -c SOURCE_FILE
# extract parameters
SOURCE_FILE="${#: -1:1}"
OBJECT_FILE="${#: -3:1}"
# invoke compiler
{ "$#" 2> >(sed 's#^/mnt/d/demo/##'|sed "s/warning/${esc}[32m&${esc}[0m/g"|sed "s/error/${esc}[31m&${esc}[0m/g" >&3); } 3>&2
it would output stderr messages also on stderr and transform it to relative path.Where "/mnt/d/demo/" is the string to be deleted. What to delete depends on the source code relative path.
(2)You can use the following command from gdb for remapping to solve the second problem:
set substitute-path old_path new_path
You need add follow code to you launch.json
"customLaunchSetupCommands": [
{
"text": "set substitute-path /mnt/d d:/",
"description": "change directory to workspace",
"ignoreFailures": false
}
]
If you debug with Cortex Debug you should add follw code to you launch.json
"postLaunchCommands": ["set substitute-path /mnt/d d:/"]

Related

How to get the working directory of the cmake process?

How to get the working directory from which cmake was called?
I know that I can run execute_process() at the beginning of my CMake code but maybe there is some better way like a built-in variable to the working directory of the CMake process.
What I want to achieve is to convert a relative path given in a CMake variable (given with -D...) to an absolute path in CMake.
What I want to achieve is to convert a relative path given in a CMake variable (given with -D...) to an absolute path in CMake.
Then simply create a cache variable of type PATH (for directories) or FILEPATH in your CMakeLists.txt. CMake will convert untyped command line arguments to absolute paths automatically.
$ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(test NONE)
set(input_file "" CACHE FILEPATH "some input file")
message(STATUS "${input_file}")
$ cmake -S . -B build -Dinput_file=foo.txt
-- /path/to/foo.txt
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/build
See the documentation:
It is possible for the cache entry to exist prior to the call but have no type set if it was created on the cmake(1) command line by a user through the -D<var>=<value> option without specifying a type. In this case the set command will add the type. Furthermore, if the <type> is PATH or FILEPATH and the <value> provided on the command line is a relative path, then the set command will treat the path as relative to the current working directory and convert it to an absolute path.
Here: https://cmake.org/cmake/help/latest/command/set.html?highlight=current%20working%20directory
Relatedly, when running in script mode (rather than project mode), several of the usual variables are set to the current working directory:
When run in -P script mode, CMake sets the variables CMAKE_BINARY_DIR, CMAKE_SOURCE_DIR, CMAKE_CURRENT_BINARY_DIR and CMAKE_CURRENT_SOURCE_DIR to the current working directory.
https://cmake.org/cmake/help/latest/variable/CMAKE_SOURCE_DIR.html

Visual Studio says Acces is Denied when trying to run with F5 or Ctrl-F5 [duplicate]

I am using CMake to generate Visual Studio projects. Everything works fine except one thing.
The startup project in the solution is always ALL_BUILD. How do I change the startup project to the real project I want via CMake?
CMake now supports this with versions 3.6 and higher through the VS_STARTUP_PROJECT directory property:
cmake_minimum_required(VERSION 3.6)
project(foo)
# ...
add_executable(bar ${BAR_SOURCES})
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT bar)
This will set bar as the startup project for the foo.sln solution.
You can't. The startup-project is stored in a binary file, which is NOT generated by CMake. Without that binary file, visual studio will default to the first project in the solution file and the ALL_BUILD project is always first...
Update: this answer is "out-of-date" since it is now feasible with CMake 3.6. See the answer by ComicSansMS.
Since Visual 2005, the configuration is stored in a file name projectname.vc(x)proj.user, which is plain xml.
I don't know about a way to change the startup project, but you certainly can set ALL_BUILD to run the desired executable instead of displaying the stupid popup :
create_default_target_launcher(
your_desired_target_name
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/desired_path/"
# or ${CMAKE_CURRENT_BINARY_DIR}, depending on your setup
)
This module is available on rpavlik's github. You simply need to add this in your topmost CMakeLists.txt :
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/external/rpavlik-cmake-modules-1c73e35") # or whichever path you put the module in.
include(CreateLaunchers)
Examples available here.
If you can't allow a perl dependency like me, I just wrote a little command line utility for windows called slnStartupProject to solve this. It sets the Startup Project automatically like this:
slnStartupProject slnFilename projectName
I personally use it to set the project after generating the solution with cmake that always sets a dummy ALL_BUILD project as the first project in the solution.
The source is on github:
https://github.com/michaKFromParis/slnStartupProject
Forks and feedbacks are welcome.
Hope this helps!
It is correct that the explicit choice the user makes when hitting "Set as startup project" in IDE is stored in a binary file. But I found somewhere else that Visual Studio takes the first Project in the solution as an implicit Startup Project when first opening a solution, so CMake does have an influence on this.
Our problem now: ALL_BUILD is always the first project. To change this, I am running a short perl script after CMake that cuts the desired project definition out of the file and pastes it into the front. Path to solution file in first parameter, project name in second:
use strict;
use File::Spec;
# variables
my $slnPath = File::Spec->rel2abs($ARGV[0]);
my $projectName = $ARGV[1];
my $contents;
my $header;
my $project;
my $GUID = "[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}";
my $fh;
# read file content (error if not found)
print "Setting \"$projectName\" as Startup Project in \"$slnPath\"...\n";
die "Error: path \"$slnPath\" not found!\n" if not -f $slnPath;
open($fh, "<", $slnPath) or die "Error: cannot read $slnPath: $!";
$contents = do { local $/; <$fh> };
close($fh) or warn "close failed: $!";
# extract part before Projects definition section (the first mention of "Project([GUID])")
$header = $1 if $contents =~ s{(.*?(?=Project\("\{${GUID}\}"\)))}{}si;
# extract definition of the project specified (error if not found)
$project = $1 if $contents =~ s{(Project\("\{${GUID}\}"\) = \"${projectName}\".*?EndProject\s)}{}si;
die "Error: Project not found!\n" if not defined $project or not length $project;
# write header, project definition and remaining content back into the file
`attrib -R "$slnPath"`;
open($fh, ">", $slnPath) or die "Error: cannot write to $slnPath: $!";
print $fh $header, $project, $contents;
close($fh) or warn "close failed: $!";
print "Successfully done.\n";
Once the solution has been opened, the implicit startup project is saved in the binary file and thus becomes explicit, so this even survives a CMake rerun (e.g. triggered by ZERO-CHECK, which doesn't allow post-execution). In the same way, anm explicit user choice is also preserved.
(Written and tested on Win7 machine with ActiveState Perl)
With cmake 3.5, the startup project (for VS 2010) can be changed with
SET(CMAKE_DEFAULT_STARTUP_PROJECT myFavoriteProject)
in the main CMakeLists.txt of the project.
By default, it is set to ALL_BUILD.

CMAKE keeps giving error "does not appear to contain CMakeLists.txt"

I am trying to figure out CMake and can't seem to figure out this basic issue. Every time I try to configure the project using CMake GUI it gives me an error stating the "source directory does not appear to contain CMakeLists.txt" when it clearly does. The text of the CMakeLists.txt file is:
cmake_minimum_required(VERSION "3.19.0")
project("Hello_World")
add_executable("${PROJECT_NAME}" "main.cpp")
install (TARGETS "${PROJECT_NAME}" DESTINATION bin)
install (FILES "main.cpp" DESTINATION src)
Also here is an image of my screen with all the relevant info:
When I navigate to the Hello_World directory in the console and enter cmake, I get this:
Usage
cmake [options] <path-to-source>
cmake [options] <path-to-existing-build>
cmake [options] -S <path-to-source> -B <path-to-build>
Specify a source directory to (re-)generate a build system for it in the
current working directory. Specify an existing build directory to
re-generate its build system.
Run 'cmake --help' for more information.
What am I missing? Any help would be appreciated. Thanks.
What happens if you open a console, change to the Hello-World-Directory and call 'cmake'?
I figured it out. For those struggling with the same issue see this video: https://www.youtube.com/watch?v=gYmgbqGfv-8
The issue is that you must go into the View settings of the Windows Explorer and make sure that the "file name extensions" box is checked so that Windows won't consider your file extension to be part of the file name. Such as CMakeLists.txt.txt.

CMake Error: cmake don't find source directory or CMakeLists.txt (installing Ogre3D)

so I've tried to use the cmake on ogre to install it but every time I use the command in the directory build :
cmake ..
I've got this error which show up :
CMake Error: The source directory "/home/.../TPs/ogre" does not exist.
Specify --help for usage, or press the help button on the CMake GUI.
and after doing :
cmake .. -DCMAKE_MODULE_PATH=/usr/share/OGRE/cmake/modules/
the error transformed in :
CMake Error: The source directory "/home/.../TPs/ogre" does not appear to contain CMakeLists.txt.
Specify --help for usage, or press the help button on the CMake GUI.
although it got a CMakeLists.txt.
I've got cmake 2.8.XXX version and python 2.7.XXX, I've tried to use cmake-gui but it also gave me an error about the CMakeCache ...
So do you have any advice?
EDIT : Ok it works, moral of the story, even if you strongly want it, don't ever put '\' in folder names !
Be sure you have activated your virtual env. If you are not, then delete previus build folder. Activate virtual env you want. Make new build folder inside opencv. Then execute cmake.

cmake - get the used commandline flags "-D"

i recently switched a few projects from autotools to cmake.
one common thing i liked on autotools is that - if i go into the src build directory. there is config.log/config.status - where at the top the ./configure --params command is listed - so it is easy to rerun the former used commandline flags.
(like after compiling some stuff - i want to add a another --enable-this - so copy & paste from config.log/status - and rerun the ./configure --old-params --enable-this)
in cmake - i have a bunch of -D flags - how can i find the used commandline like in config.log/status - with a cmake project?
i know there is the CMakeCache... - but its hard to extract the used flags
edit:
i came up with the following solution:
#save commandline to rebuild this :)
set(USED_CMD_LINE "cmake ")
set(MY_CMAKE_FLAGS CMAKE_BUILD_TYPE CMAKE_INSTALL_PREFIX ENABLE_SSL ENABLE_LUA ENABLE_SSH ENABLE_SNMP MYSQL_USER MYSQL_PASS MYSQL_HOST MYSQL_DB FULL_FEATURES USE_COVERAGE)
FOREACH(cmd_line_loop IN ITEMS ${MY_CMAKE_FLAGS})
if(${cmd_line_loop})
STRING(CONCAT USED_CMD_LINE ${USED_CMD_LINE} "-D" ${cmd_line_loop} "=" ${${cmd_line_loop}} " ")
endif()
ENDFOREACH(cmd_line_loop)
STRING(CONCAT USED_CMD_LINE ${USED_CMD_LINE} " .. ")
#store to a file aka "config.status"
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/config.status ${USED_CMD_LINE} )
creates a file config.status in the build folder - containing all set cmake params.
pro:
seems to solve my problem
seems to work on subsequent cmake calls
con:
unable to set chmod on FILE(write ? the variable
MY_CMAKE_FLAGScontains the known flags - needs to be manually
updated if a new flag is added
regards
Cmake does not give you easy way to list all used -D flags (defines). However, for correctly written CMakeLists, it is not needed to know the full command line with all -D flags to change one particular define/option.
Consider this snipplet:
SET(my_var_1 TRUE CACHE BOOL "my var 1")
SET(my_var_2 TRUE CACHE BOOL "my var 2")
message(STATUS "my_var_1 ${my_var_1}")
message(STATUS "my_var_2 ${my_var_2}")
First cmake invocation:
>cmake .. -Dmy_var_1=FALSE
-- my_var_1 FALSE
-- my_var_2 TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: out
Second cmake invocation:
>cmake .. -Dmy_var_2=FALSE
-- my_var_1 FALSE
-- my_var_2 FALSE
-- Configuring done
-- Generating done
-- Build files have been written to: out
Note that my_var_1=FALSE even it is not explicitely stated (taken from cache)
One feature that may be helpful is turning on the flag CMAKE_EXPORT_COMPILE_COMMANDS in the project's CMake cache. During build, this will make CMake generate a JSON file compile_commands.json in the binary directory that contains the exact compiler calls for all translation units.
You may want to take a look at what is done in the bootstrap script in CMake's source code:
# Write our default settings to Bootstrap${_cmk}/InitialCacheFlags.cmake.
echo '
# Generated by '"${cmake_source_dir}"'/bootstrap
# Default cmake settings. These may be overridden any settings below.
set (CMAKE_INSTALL_PREFIX "'"${cmake_prefix_dir}"'" CACHE PATH "Install path prefix, prepended onto install directories." FORCE)
set (CMAKE_DOC_DIR "'"${cmake_doc_dir}"'" CACHE PATH "Install location for documentation (relative to prefix)." FORCE)
set (CMAKE_MAN_DIR "'"${cmake_man_dir}"'" CACHE PATH "Install location for man pages (relative to prefix)." FORCE)
set (CMAKE_DATA_DIR "'"${cmake_data_dir}"'" CACHE PATH "Install location for data (relative to prefix)." FORCE)
' > "${cmake_bootstrap_dir}/InitialCacheFlags.cmake"
[...]
"${cmake_bootstrap_dir}/cmake" "${cmake_source_dir}" "-C${cmake_bootstrap_dir}/InitialCacheFlags.cmake" "-G${cmake_bootstrap_generator}" ${cmake_options} ${cmake_bootstrap_system_libs} "$#"
The boostrap script is generating a InitialCacheFlags.cmake file and is then preloading it with the cmake -C option.
And - if you additionally want to output the values to stdout - this initial-cache CMake script also accepts message() commands besides the set(... CACHE) commands.
See also How to store CMake build settings