CMAKE - Changing outdir macro through cmake - directory

Reading others questions here I found that is possible to change the outdir macro inside de visual studio. I really searched but didn't found/understand how to do it.
It's kind simple. I just want to change the Project property -> Configuration Properties -> General -> Output Directory. Because I know that will change the outdir macro.
I understand that is throught set_target_property using some kind of cmake PROPERTY but I really didn't found how.

It's pretty straightforward as you suspected. You need to look at the ARCHIVE_OUTPUT_DIRECTORY, LIBRARY_OUTPUT_DIRECTORY, and RUNTIME_OUTPUT_DIRECTORY target properties to modify the outdir path.
These all have config-specific variants too (e.g. ARCHIVE_OUTPUT_DIRECTORY_DEBUG) and can all be initialised by the global CMake variables of the same name with a CMAKE_ prepended.
So, you can do e.g.
set_target_properties(MyExe PROPERTIES RUNTIME_OUTPUT_DIRECTORY <custom path>)
or, to affect all targets,
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY <custom path>)
NB. From the docs:
Multi-configuration generators (VS, Xcode) append a per-configuration subdirectory to the specified directory.
Here's an example showing this behaviour. It writes its own trivial C++ source files, so all you should need to do is copy this to a folder, invoke CMake then try building the resultant solution in Debug, Release, MinSizeRel and RelWithDebInfo. Tested with VS2012. The executable always ends up in <build dir>/Exes/Debug regardless of build type, and similarly the library is always in <build dir>/Libs/Debug.
cmake_minimum_required(VERSION 2.8.11 FATAL_ERROR)
project(Example)
file(WRITE lib.hpp "void Print();\n")
file(WRITE lib.cpp "#include<iostream>\nvoid Print() { std::cout << \"Hello World\\n\"; }\n")
file(WRITE main.cpp "#include \"lib.hpp\"\nint main() { Print(); return 0; }\n")
set(ArchiveOutputDir ${CMAKE_BINARY_DIR}/Libs/Debug)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${ArchiveOutputDir})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL ${ArchiveOutputDir})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${ArchiveOutputDir})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${ArchiveOutputDir})
set(RuntimeOutputDir ${CMAKE_BINARY_DIR}/Exes/Debug)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${RuntimeOutputDir})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${RuntimeOutputDir})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${RuntimeOutputDir})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${RuntimeOutputDir})
add_library(MyLib lib.cpp lib.hpp)
add_executable(MyExe main.cpp)
target_link_libraries(MyExe MyLib)

In the end, what worked for me was placing the full path on the target_link_libraries with debug prefix and optimized prefix to point release config and relwithdebinfo config to release path and debug to debug. I also took off the link_directories... I don't if I didn't understand but it worked for me!

Related

QMake 5.15 don't understand wildcard adding files [duplicate]

I have a .pro file which looks like:
SOURCES += myfolder/source1.cpp \
myfolder/source2.cpp
HEADERS += myfolder/header1.h\
myfolder/header2.h
FORMS += myfolder/form1.ui\
myfolder/form2.ui
And everything works great. However, if I try to use an asterisk to include all the files, i.e.:
SOURCES += myfolder/*.cpp
HEADERS += myfolder/*.h
FORMS += myfolder/*.ui
qmake throws a file-not-found-error:
WARNING: Failure to find: myfolder\*.cpp
[...]
:-1: error: No rule to make target `myfolder/*.cpp', needed by `release/source1.o'. Stop.
In both cases, Qt-Creator can find the files.
Is there a way to use the asterisk? It's annoying to type the files manually.
Thank you!
[EDIT: Qt 4.8.4, Windows 7, Qt-Creator 2.6.1. Sry for forgetting this thought it isnt needed.]
[EDIT: Found solution: http://qt-project.org/forums/viewthread/1127 . Thank you anyway!]
In qmake 3.0, at least, it's possible to use something like:
SOURCES = $$files(*.cpp, true)
HEADERS = $$files(*.h, true)
The true argument will cause the files function to recursively find all files matching the pattern given by the first argument.
At first, using asterisk is bad practice - despite that qmake allows it, QtCreator cannot edit such *.pro correctly on adding new, renaming or deleting file. So try to add new files with "New file" or "Add existing files" dialogs.
QMake has for loop and function $$files(directory_path: String). Also append files to SOURCES or HEADERS variable respectively.
Brief example, which adds all files, but not directories, to variable FILES (not affect build or project tree):
files = $$files($$PWD/src)
win32:files ~= s|\\\\|/|g
for(file, files):!exists($$file/*):FILES += $$file
If you want to check if file is *.cpp, try to use contains($$file, ".cpp").
files = $$files($$PWD/src)
win32:files ~= s|\\\\|/|g
for(file, files):!exists($$file/*):contains($$file, ".cpp"):SOURCES += $$file

Documentation error "qdoc can't run; no project set in qdocconf file"

I am trying to generate documentation for my code using QDoc. qtdoc command is already in my environment variable path. But when I try to run the command in the root directory of the project (qdocconf file also resides in project root),
qdoc projectname.qdocconf
I get the following error
qt.qdoc: "qdoc can't run; no project set in qdocconf file"
Here is my projectname.qdocconf file.
headers.fileextensions = "*.h *.hpp"
sources.fileextensions = "*.cpp *.qml *.qdoc"
outputdir = Documentation/Code
headerdirs += Code
sourcedirs += . \
Code
exampledirs = .
imagedirs += ./Images/icons \
./Images/logos
I have commented on my class functions as described in the documentation using the format
/*!
* \fn void inlineFunction()
*
* Some info here...
*/
Can you point me what am I doing wrong?
Also, can I create the documentation using QtCreator instead of running the command in terminal?
Well somehow I figured out that you need to add the following line in your .qdocconf file
project = YourProjectName
which is not present in the minimum qdocconf file presented in https://doc.qt.io/qt-5/qdoc-minimum-qdocconf.html. Even though the above issue was resolved, a lot of other issues were encountered such as:
While compiling, qt.qdoc: No include paths passed to qdoc; guessing reasonable include paths. For this you have to manually include all the source paths. Read: https://bugreports.qt.io/browse/QTBUG-67289
Some comment tags, e.g. \return, \param, present in QtCreator are not recognized by QDoc
Option 2
Alternatively, look for Doxygen which is much easier to use and generate documents with a simple to use GUI. It also recognizes all the comment tags in QtCreator.
Update:
Doxygen plugins for Qt Creator doesn't work anymore as the support has expired. Use Doxygen GUI directly.

Qt - Using asterisk (*) in .pro-File with directories

I have a .pro file which looks like:
SOURCES += myfolder/source1.cpp \
myfolder/source2.cpp
HEADERS += myfolder/header1.h\
myfolder/header2.h
FORMS += myfolder/form1.ui\
myfolder/form2.ui
And everything works great. However, if I try to use an asterisk to include all the files, i.e.:
SOURCES += myfolder/*.cpp
HEADERS += myfolder/*.h
FORMS += myfolder/*.ui
qmake throws a file-not-found-error:
WARNING: Failure to find: myfolder\*.cpp
[...]
:-1: error: No rule to make target `myfolder/*.cpp', needed by `release/source1.o'. Stop.
In both cases, Qt-Creator can find the files.
Is there a way to use the asterisk? It's annoying to type the files manually.
Thank you!
[EDIT: Qt 4.8.4, Windows 7, Qt-Creator 2.6.1. Sry for forgetting this thought it isnt needed.]
[EDIT: Found solution: http://qt-project.org/forums/viewthread/1127 . Thank you anyway!]
In qmake 3.0, at least, it's possible to use something like:
SOURCES = $$files(*.cpp, true)
HEADERS = $$files(*.h, true)
The true argument will cause the files function to recursively find all files matching the pattern given by the first argument.
At first, using asterisk is bad practice - despite that qmake allows it, QtCreator cannot edit such *.pro correctly on adding new, renaming or deleting file. So try to add new files with "New file" or "Add existing files" dialogs.
QMake has for loop and function $$files(directory_path: String). Also append files to SOURCES or HEADERS variable respectively.
Brief example, which adds all files, but not directories, to variable FILES (not affect build or project tree):
files = $$files($$PWD/src)
win32:files ~= s|\\\\|/|g
for(file, files):!exists($$file/*):FILES += $$file
If you want to check if file is *.cpp, try to use contains($$file, ".cpp").
files = $$files($$PWD/src)
win32:files ~= s|\\\\|/|g
for(file, files):!exists($$file/*):contains($$file, ".cpp"):SOURCES += $$file

Qt Creator and conditional build

In our project, we added some source and header files if a MACRO is defined. We do this like that, in the .pro file:
contains(DEFINES, MY_DEF) {
message("Support MY_DEF")
INCLUDEPATH += \
my_include_dir
SOURCES += \
source1.cpp \
source2.cpp
HEADERS += \
my_include_dir/header1.h \
my_include_dir/header2.h
FORMS += \
myform.ui
}
This works fine during the build. The files are not compiled if MY_DEF is not defined. MY_DEF is defined like that:
DEFINES += MY_DEF
Curiously, Qt Creator always display the files in the project tree, whereas MY_DEF is defined or not. If not defined, they are not used for the build, but they still are displayed and editable, searches can scan them, etc... Is it a bug of Qt Creator?
This is not a big issue, just a little annoying, because we don't know clearly if a file is part of the project or not.
It's intentional even. There's a special "accumulating" parsing mode to collect all files that are mentioned in .pro files (essentially the same that's used to collect "translatable strings") for display in the project tree. Otherwise things like "Replace in all files in a project" would yield different results depending on the platform or the context it is run in. [And it's not half of qmake that's included, but close to all of it...]
This seems to be an issue with QtCreator and how it reads the .pro files - it doesn't seem to actually fully parse the files, opting instead to just pick out certain bits. I've got the same issue with files that are only included on one platform or another - in QtCreator, they always show up.
I expect that the reason is either that they don't want to re-implement half of qmake just to get the file lists, OR that there are situations where trying to parse it 'correctly' would get the wrong answer, and they've chosen to be predictably wrong instead of randomly wrong.
In addition to the conditional includes in QMake, I add #ifdef around such conditional source code. That way I also see it visually drop out of compilation when the conditions are not met. It's not as good as having the files drop out entirely from the project tree, but it's better than allowing them to still appear like they are part of the build when editing them if they are not applicable.
Just for the sake of completeness and answer correctness. Probably someone else needs this example of root .pro file with conditional source tree:
TEMPLATE = subdirs
SUBDIRS = device
CONFIG -= debug_and_release
_SANDBOX_DIR = $$dirname(PWD)
_PLAYER_PRO = $${_SANDBOX_DIR}/player/player.pro
SUBDIRS = device
device.subdir = $${_SANDBOX_DIR}/proxy/libproxy
contains(QMAKE_PLATFORM, android) {
unset(_PLAYER_PRO)
} else {
SUBDIRS += player
player.file = $${_PLAYER_PRO}
player.depends = device
}
SUBDIRS += app
app.subdir = $${_SANDBOX_DIR}/display/display
app.depends = device
contains(SUBDIRS, player) {
app.depends += player
}

CMake : detect "Q_OBJECT" in a file and add it to a list of file to treat by MOC

Currently, I use a variable MYPROJECT_CURRENT_HEADERS in CMake to list all the headers. As I use Qt, my CMakeLists.txt contains :
QT4_WRAP_CPP(MYPROJECT_CURRENT_MOC ${MYPROJECT_CURRENT_HEADERS})
The problem is that all headers are treated by moc, even those that don't have a Q_OBJECT : so it generates many empty file.
Is there a solution to "grep"/detect if the file contains the string Q_OBJECT and if it's the case, add it to MYPROJECT_CURRENT_MOC ?
Thank you
There's a new target property in the soon-to-be-released CMake 2.8.6 called "AUTOMOC" that may help you out.
The test for this feature (which you can use as a guide or example) is found here:
http://cmake.org/gitweb?p=cmake.git;a=tree;f=Tests/QtAutomoc;h=7dae3b16a54dc0b2f63bbfa5c218c48b9bbf34a9;hb=nightly-master
The very simple CMakeLists.txt file is here:
http://cmake.org/gitweb?p=cmake.git;a=blob;f=Tests/QtAutomoc/CMakeLists.txt;h=4a5ff1099ba5249a6f22eea745a031b76e6f440f;hb=nightly-master
If you use this feature, cmake will scan the headers for Q_OBJECT and automatically run moc for you.
If you'd like to try it out before the final release of CMake 2.8.6, you can download one of the release candidates here:
http://cmake.org/files/v2.8/?C=M;O=D
The "-rc2" files do include the AUTOMOC property.
Here's the help text from running "cmake --help-property AUTOMOC":
cmake version 2.8.6-rc2
AUTOMOC
Should the target be processed with automoc (for Qt projects).
AUTOMOC is a boolean specifying whether CMake will handle the Qt moc
preprocessor automatically, i.e. without having to use the
QT4_WRAP_CPP() macro. Currently Qt4 is supported. When this property
is set to TRUE, CMake will scan the source files at build time and
invoke moc accordingly. If an #include statement like #include
"moc_foo.cpp" is found, the Q_OBJECT class declaration is expected in
the header, and moc is run on the header file. If an #include
statement like #include "foo.moc" is found, then a Q_OBJECT is
expected in the current source file and moc is run on the file itself.
Additionally, all header files are parsed for Q_OBJECT macros, and if
found, moc is also executed on those files. The resulting moc files,
which are not included as shown above in any of the source files are
included in a generated _automoc.cpp file, which is
compiled as part of the target.This property is initialized by the
value of the variable CMAKE_AUTOMOC if it is set when a target is
created.
I don't know a simple command to pick headers having a string from the list but you can always make a loop to find all such headers:
set(HEADERS_HAVING_Q_OBJECT)
foreach(header ${MYPROJECT_CURRENT_HEADERS})
file(STRINGS "${header}" lines REGEX "Q_OBJECT")
if(lines)
list(APPEND HEADERS_HAVING_Q_OBJECT "${header}")
endif()
endforeach()
But this solution has its own drawback: if you add a Q_OBJECT into one of the filtered out files you need to rerun cmake manually. Otherwise moc code for new file will not be automatically generated during the build process.

Resources