While reading through the documentation for Qt 5.1, and specifically qmake, I was stumped by the explanation given in the documentation for the qmake CONFIG() function. I completely understood the one-argument version of the function, but the two-argument version makes absolutely no sense to me. I think my confusion is coming from the lack of a definition for 'active config' since the Qt 5.1 documentation says the following:
This function can be used to test for variables placed into the CONFIG variable. This is the same as scopes, but has the added advantage that a second parameter can be passed to test for the active config. As the order of values is important in CONFIG variables (that is, the last one set will be considered the active config for mutually exclusive values) a second parameter can be used to specify a set of values to consider.
I would greatly appreciate an explanation for this concept of 'active config' as I am completely stumped and cannot make any practical sense out of this second argument.
The CONFIG variable can contain conflicting options, such as both "release" and "debug". If CONFIG contains both "release" and "debug" at the same time then either "release" or "debug" is effective. The interpretation of conflicting options in CONFIG depends on the order: the last one set will be considered the effective or active config.
Using CONFIG() with one parameter tells you whether an option is present or not in CONFIG variable. If both "release" and "debug" are present then both CONFIG(release) and CONFIG(debug) returns true.
Using CONFIG() with two parameters tells you whether an option is effective or not, is it the active config or not. CONFIG(debug, debug|release) tests whether "debug" is the last (and hence, active) among the "debug" and "release" options.
See this question and answer as well.
EDIT:
I've created a new project with Qt Creator, opened the .pro file generated and added the following line at the bottom: message($${CONFIG}) so that we can see the contents of CONFIG when qmake is run. I show you the whole .pro file:
QT += core
QT -= gui
TARGET = QMakeConfigTest
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
message($${CONFIG})
There are two lines where CONFIG is modified, only one option is added and one is removed. Then I've chosen Release Build and run qmake. This is what I see in Compile Output window:
08:53:49: Running steps for project QMakeConfigTest...
08:53:49: Starting: "C:\Qt\Qt5.0.2\5.0.2\msvc2010\bin\qmake.exe"
C:\QMakeConfigTest\QMakeConfigTest.pro -r -spec win32-msvc2010
Project MESSAGE: lex yacc debug exceptions depend_includepath
testcase_targets import_plugins import_qpa_plugin rtti_off
incremental_off windows qt warn_on release link_prl incremental flat
precompile_header autogen_precompile_source debug_and_release
debug_and_release_target embed_manifest_dll embed_manifest_exe
copy_dir_files release shared rtti qpa win32 msvc debug DebugBuild
Debug build_pass console
08:53:49: The process "C:\Qt\Qt5.0.2\5.0.2\msvc2010\bin\qmake.exe"
exited normally.
08:53:49: Elapsed time: 00:00.
As you can see the CONFIG variable contains a lot of default options beside the console option added in the .pro file. It contains both debug and release twice and debug_and_release once.
Where are these default options coming from? They are defined in .prf and .conf files that are loaded from a directory called mkspecs. So the answer to the question you asked in your comment is that before a .pro file is processed by qmake several other files are pre-processed based on your compiler and platform. These files can add the same options more than once and can add conflicting options to the CONFIG variable.
Here is the contents of C:\Qt\Qt5.0.2\5.0.2\msvc2010\mkspecs\features\default_pre.prf:
# This file is loaded by qmake right before each actual project file.
# Note that evaluating variable assignments from the command line
# still happens in between these two steps.
load(exclusive_builds)
CONFIG = \
lex yacc debug exceptions depend_includepath \
testcase_targets import_plugins import_qpa_plugin \
$$CONFIG
As you can see the first 8 default options are defined in this file.
The contents of C:\Qt\Qt5.0.2\5.0.2\msvc2010\mkspecs\features\win32\default_pre.prf:
CONFIG = rtti_off incremental_off windows $$CONFIG
load(default_pre)
The relevant part of C:\Qt\Qt5.0.2\5.0.2\msvc2010\mkspecs\features\spec_pre.prf:
# This file is loaded by qmake right before loading the qmakespec.
# At this point, the built-in variables have been set up and the project's
# .qmake.super was read (if present).
CONFIG = qt warn_on release link_prl
QT = core gui
Qt Creator runs qmake.exe with the following option: -spec win32-msvc2010. Let's see the qmake manual about the -spec option:
-spec spec: qmake will use spec as a path to platform and compiler information,
and the value of QMAKESPEC will be ignored.
The first few lines from C:\Qt\Qt5.0.2\5.0.2\msvc2010\mkspecs\win32-msvc2010\qmake.conf:
#
# qmake configuration for win32-msvc2010
#
# Written for Microsoft Visual C++ 2010
#
MAKEFILE_GENERATOR = MSBUILD
QMAKE_PLATFORM = win32
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
QMAKE_COMPILER_DEFINES += _MSC_VER=1600 WIN32
Related
I'm working on adding DLL hotloading to a C++ app. Because of this, I open 2 instances of MSVC: 1 instance runs the app while I code and compile on the other instance. Breakpoints are hit on the first instance, and I can continue to code on the 2nd instance without stopping the app.
To support this, I need to read and write to a (semi) persistent CMake variable between builds. I use that variable to decide how to name the generated files. That is, every time I compile some hot loadable DLL, I need to cycle between names to give the files being generated, because the previous files are in use by running app.
So, the generated files would cycle as:
path/to/some.a.pdb
path/to/some.b.pdb
How can I read/write to a variable every build/compile, which remembers the value from the previous compile. The CMakeCache doesn't work for this, because it gets set during the configure phase and not updated during the generation phase. Maybe it could be done with Generator Expressions.
I'm pretty sure you can use CMAKE_<CONFIG>_POSTFIX. Yes, you need to reconfigure, but it won't run into problems with writing to open/mapped libraries.
From the documentation
Default filename postfix for libraries under configuration <CONFIG>.
When a non-executable target is created its <CONFIG>_POSTFIX target property is initialized with the value of this variable if it is set.
and this piece of documentation:
Postfix to append to the target file name for configuration .
When building with configuration <CONFIG> the value of this property is appended to the target file name built on disk. For non-executable targets, this property is initialized by the value of the variable CMAKE_<CONFIG>_POSTFIX if it is set when a target is created. This property is ignored on the Mac for Frameworks and App Bundles.
You can cycle between different postfixes like so:
$ cmake -B build -DCMAKE_RELEASE_POSTFIX=_a
$ cmake --build build/ --config Release --target MySwappableDll
... start your app, which loads the _a libraries ...
... later, when you want to rebuild and swap out to _b, just reconfigure ...
$ cmake -B build -DCMAKE_RELEASE_POSTFIX=_b
$ cmake --build build/ --config Release --target MySwappableDll
... now the _b targets are incrementally built and you can hot swap ...
You can also use RelWithDebInfo or Debug or even a totally custom config (you could even create an "A" and a "B" config with different postfixes so you wouldn't need to re-run the configure step).
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.
I understand that by default, Clion creates the binary files for a project loaded in Clion in all the four configurations:
(Debug;Release;MinSizeRel;RelWithDebInfo)
as well as one called: __default__.
I am using a third party cmake module which downloads an external project in a way that add_subdirectory() can be run on it so it would be included in the root project.
add_subdirectory(${downloaded_proj_src_dir} ${downloaded_proj_bin_dir} EXCLUDE_FROM_ALL)
In this setup, if I decide to place the child project outside the binary directory of the root project, I get:
Error:Binary directories outside of CMake build directory are not supported. Most likely this error is caused by an add_subdirectory command with an explicitly specified binary_dir argument.
which is an understandable restriction by CMake.
now if I instead decide to set the binary directory of the downloaded project in a subdirectory of the binary directory of the parent project, ie:
set(downloaded_proj_bin_dir "${CMAKE_BINARY_DIR}/${downloaded_proj}-build")
...
add_subdirectory(${downloaded_proj_src_dir} ${downloaded_proj_bin_dir} EXCLUDE_FROM_ALL)
I will get the file created in the parent binary directory of all the build configurations because ${CMAKE_BINARY_DIR} is different for each configuration. To avoid seeing all these directories listed on the project view sidebar, I have set the CMAKE_CONFIGURATION_TYPES to be Debug. But even then, I get:
Error:Configuration Debug
The current CMakeCache.txt directory /path/Debug/downloaded_proj_bin/CMakeCache.txt is different than the directory /path/__default__/downloaded_proj_bin/CMakeCache.txt where CMakeCache.txt was created. This may result in binaries being created in the wrong place. If you are not sure, reedit the CMakeCache.txt
Clearly something is going on with this __default__ configuration which I don't understand. So the question is, what is the significance of this default configuration and why should there be a conflict here?
P.s. Setting the configuration to __default__ does not solve the problem as I will have a __default__0 configuration created instead and get the same error.
Update: some further observations
My enviornment variables set in IDE don't have any effect on the cmake builds.
Cmake "options" however which presumably will be passed as arguments to cmake do seem to work.
-D CMAKE_CONFIGURATION_TYPES=Debug.
When I specify the command line option, I get
Warning:Manually-specified variables were not used by the project:
CMAKE_CONFIGURATION_TYPES
But it clearly does have the effect of no longer creating the other build configurations. My guess is that this message relates to the __default__ build which is ignoring the argument.
Even in the case of specifying CMAKE_CONFIGURATION_TYPES in the IDE, I still get the additional __default__ build which is apparently unaffected by the CMAKE_CONFIGURATION_TYPES assignment.
Logging: message("Build type: ${CMAKE_BUILD_TYPE} ) does not return any build_type.
Outputting message(and generator: ${CMAKE_GENERATOR} ") returns "Unix-make files" for both, so both are being generated with the same generator.
Taking a diff from the CMakeCache.txt files, I can see that they are identical.
Do you have in DownloadProject.cmake the right setting? for:
set(_DownloadProjectDir "${CMAKE_CURRENT_LIST_DIR}")
I had the same problem trying to set google test(with the help of https://github.com/Crascit/DownloadProject) and my _DownloadProjectDir was setted as "test". Maybe when I moved this cmake file in my project Clion changed that automatically.
So, it turns out that you can sort this out quite easily by adding the following line above line 145 in DownloadProject.cmake:
file(REMOVE "${DL_ARGS_DOWNLOAD_DIR}/CMakeCache.txt")
This seems to be because CLion copies the default across to the other configurations and doesn't clear the cache. This is a problem only because DownloadProject creates a project within the project (I think...). Anyway, deleting this file before configuring the CMakeLists.txt by-passes this issue. I'll submit a pull request to the DownloadProject repository as this doesn't seem to have any adverse effects when not using CLion.
So I'm using CMake for a project.
It consists of a set of shared libraries linked to one executable. All are generated in the project (there are no external targets). Each sub project lives in its own directory, with its own cmakelists file.
So I make an out-of-source build, taking care to set CMAKE_BUILD_TYPE to Debug, and run cmake, and then make. I use GNU make 3.81, GCC 4.8.1, binutils 2.23.2 and CMake 3.2.3 on a Windows box using MSYS/MINGW.
The problem is that, when I load this executable in gdb (version 7.6), place a breakpoint on a function from one of the shared libraries, and then try to single step, gdb skips the whole function saying it has no line number information.
According to my understanding, line number information is a part of the debugging information, so I expected this to be generated during the compiling process (as per the CMAKE_BUILD_TYPE) which it didn't, so I would like to know how I can get CMake to generate this line number information properly (that is, without manually adding compiler-specific options in the cmake files, although I would take that if it's the only solution).
I've tried setting CMAKE_BUILD_TYPE from the command line (when invoking the cmake utility), inside the cmakelists, and even by modifying the CMakeCache.txt, and restarting the build from an empty directory with no success. I then made sure that CMAKE_BUILD_TYPE was effectively set to Debug by using the MESSAGE command to print it's value, and it was correctly set to Debug. So then I executed 'make VERBOSE=1' to see if the correct compiler option was added, and found it correctly used the "-g" option (although I would have expected -ggdb, but more on this later). The cmake documentation and Google did not bring me any answers.
My hypothesis is that the -g option only generates basic debugging information (such as the mappings between functions and their memory addresses, and how to access their arguments) whereas -ggdb would generate more in-detail debugging information in a gdb-specific format, including said line number informations), but a troubling fact is that, when running the executable in gdb, functions defined inside the executable do have line number information, only the shared libraries don't, hence my confusion.
i'm trying to create an LLVM pass using the guide at http://llvm.org/releases/2.9/docs/WritingAnLLVMPass.html
but i'm having several problems:
i haven't many of the folder that are indicated into the guide (lib/Transform/Hello) and (Debug+Asserts), i have created them, is it right? what's the right path?
i create these: /usr/lib/llvm-2.9/lib/Transforms/Hello and /usr/lib/llvm-2.9/Debug+Asserts
when i try to make the file in the guide i have error:
.
# Makefile for hello pass
# Path to top level of LLVM heirarchy
LEVEL = /usr/lib/llvm-2.9/build #*********I MODIFY THIS!!!! ***************
# Name of the library to build
LIBRARYNAME = Hello
# Make the shared library become a loadable module so the tools can
# dlopen/dlsym on the resulting library.
LOADABLE_MODULE = 1
# Tell the build system which LLVM libraries your pass needs. You'll probably
# need at least LLVMSystem.a, LLVMSupport.a, LLVMCore.a but possibly several
# others too.
LLVMLIBS = LLVMCore.a LLVMSupport.a LLVMSystem.a
# Include the makefile implementation stuff
include $(LEVEL)/Makefile.common
and i modify also other lines into Makefile.common:
ifndef LLVM_SRC_ROOT
include $(LEVEL)/Makefile.rules
else
include $(LLVM_SRC_ROOT)/Makefile.rules
endif
because it doesn't find the Makefile.rules (in this way it works)
but now i have this error when i do make into the folder containing my hello.c file (/usr/lib/llvm-2.9/lib/Transforms/Hello):
make: *** No rule to make target "/configure", needed by "/config.status". Stop.
what's the problem?!?
Apparently, it seems you're trying to develop using the binary of the libraries. Unfortunately, this won't work. You need to download sources, build them and then start developing your own pass.
Also, 2.9 is already too ancient. Consider at least upgrading to 3.0 release.