Inside Qmake

From Initek - Wiki

Jump to: navigation, search

Contents

Table of Contents

This is a collection of notes I have put together while creating a build system at Seeing Machines.

Project Generation

Qmake performs an initial pass of the .pro file which results in a set of variables and defined functions. The behavior then changes based on whether the TEMPLATE variable ends with "subdirs" or not.

subdirs template


not-subdirs template The BUILDS variable is checked and if defined and contains more than one value the project file is processed again, once for each build. Each pass differs from the initial pass in that the following variables are set:

  • CONFIG has the contents of build.CONFIG, build and build_pass.
  • BUILD_PASS has build
  • BUILD_NAME has contents of build.name if not empty, otherwise build.

For each build a make file generator is created based on the contents of the MAKEFILE_GENERATOR variable. If the variable contains MSVC.NET or MSBUILD then then TEMPLATE variable is checked to see if it has the vc template prefix.

Variable Replacement

A variable is replaced in the context of a 'place'. A QMap from variable names to a QStringList. The variable is expanded and the resulting QStringList is joined using the field separator(' ' by default).

Variable Replace Expand space and tab separate values. $$[] is a property $${} is a var $$() is an environment variable $$name() or $${func()} is a function The following characters can be escaped: []{}()$\'" single quote and double quote strings have their quotes removed.

Builds

Specified from BUILDS {name}.CONFIG used as starting point for build pass. {name}.target - defaults to {name}. name of target in makefile

Targets

Each build in BUILDS is a a form of target. with .target.

Specified from QMAKE_EXTRA_TARGETS ( or synonyms QMAKE_EXTRA_WIN_TARGETS, QMAKE_EXTRA_UNIX_TARGETS). {name}.target - defaults to {name} {name}.commands {name}.depends list of targets this target is dependent on. {name}.CONFIG extra config flags

   recursive - For multiple BUILDS the master Makefile will contain 
           a the targets {build}-{target} for each BUILD and the target
           {target} which depends on all of them.

{name}.recurse optional list of builds, defaults to all builds {name}.recurse_target - optional override of target name in makefile

Subdirs Template SUBDIRS variable contains a list of subdirectories. The names are mapped to a possible structured variable name by replacing characters not in [a-zA-Z0-9_] with '-' characters. {mappedname}.file path to .pro file. {mappedname}.subdir {mappedname}.depends list of subdirs this subdir depends on. {mappedname}.target if not specified defaults to 'sub-' + name. The .pro file used for the subdir is name.pro if neither {mappedname}.file or {mappedname}.subdir is defined.

For each name it needs to determine the in_directory and project filename, out_directory and target


Installs

{name}.path can be empty if .CONFIG contains no_path {name}.CONFIG

   no_path - don't make {name}.path absolute
   no_check_exist
   no_build - install_name target depends on nothing
   no_default_install - don't add install to install target

{name}.uninstall {name}.extra {name}.commands same as .extra when .extra is empty {name}.files list of files searched for in VPATH and made absolute {name}.depends - targets this target depends on.

Tools

From QMAKE_EXTRA_COMPILERS(or synonyms QMAKE_EXTRA_WIN_COMPILERS, QMAKE_EXTRA_UNIX_COMPILERS) names should be lower case to match format other target names in Makefiles.

{name}.input name of variable to scan for input files. Input files can contain extra compiler

   variables.

{name}.commands command to run. Can contain extra compiler variables. {name}.output single file generated by compiler

   Text substitutions:
   ${QMAKE_FILE_IN}
   ${QMAKE_FILE_BASE}
   $(QMAKE_FILE_OUT_BASE}

{name}.name human name of compiler {name}.depends

   Text substitutions:
   ${QMAKE_FILE_IN}
   ${QMAKE_FILE_BASE}
   $(QMAKE_FILE_OUT_BASE}

{name}.depend_command Command to run which will write depends information to stdout. For the msvc generators, the command cannot contain a space as it is it uses split(' ').at(0) to determine if the file exists. The command cannot also contain an environment variable as the if exist check converts environment variables but the actual popen call doesn't! Also, the path must be relative or absolute, the PATH is not used. {name}.CONFIG

   combine combine multiple source files into a single launch of the command.
   moc_verify
   function_verify
   verify runs {name}.command and checks exit status
   no_link add output to UNUSED_SOURCES otherwise, add to OBJECTS if not there.
   target_predeps adds output file to PRE_TARGETDEPS.
   ignore_no_exist if the source file doesn't exist skip
   no_dependencies

{name}.dependency_type TYPE_UNKNOWN if not defined, TYPE_UI or everything else maps to TYPE_C {name}.verify_function list of test functions that must all pass. func(outputfile, inputfile) {name}.command command line to launch to check if it can process input file {name}.variable_out variable to add output to. SOURCES maps to "GENERATED SOURCES", OBJECTS or

   some user defined variable

Extra compiler variables: ${QMAKE_VAR_var} replace with values list from qmake variable var. ${QMAKE_VAR_FIRST_var} replace with first value from qmake variable var.

   ** THIS DOES NOT WORK. BUG IN ORDER OF COMPARISON with variable above.

${QMAKE_FUNC_FILE_IN_name} replace with result from function name(input_file) ${QMAKE_FILE_BASE} | ${QMAKE_FILE_IN_BASE} base of input name. ${QMAKE_FILE_PATH) | $(QMAKE_FILE_IN_PATH} path to input filename. ${QMAKE_FILE_NAME} | ${QMAKE_FILE_IN} name of input filename. QMAKE_FUNC_FILE_OUT_name result of name(output_file) QMAKE_FILE_OUT output filename QMAKE_FILE_OUT_BASE base of output filename QMAKE_FUNC_name name(in, out)

processing SUBDIRS variable for subdirs template subdirs are 'fixed' by replacing /[^a-zA-Z0-9_]/ with '-' subdir.file subdir.subdir subdir.makefile subdir.depends

   list of directories that this subdir is dependent on

subdir.target

makefile targets for subdirs template first qmake all clean distclean install uninstall

makefile targets for dispatching to correct build first install uninstall {build} {build}-make_default, -make_first, -all, -clean, -distclean, -install, -uninstall Makefile qmake make_default runs {build*}-make_default make_first runs {build*}-make_first all runs {build*}-all clean runs {build*}-clean distclean runs {build*}-distclean

makefile targets for macosx-g++ shared library build first all qmake dist clean compiler_clean distclean mocclean install_binaries uninstall_binaries install uninstall

Variables

Builtin

LITERAL_WHITESPACE '\t' LITERAL_DOLLAR '$' LITERAL_HASH '#' OUT_PWD output directory PWD|IN_PWD directory of current .pr[oif] file DIR_SEPARATOR '\' on windows, ':' on mac osx9, otherwise '/' DIRLIST_SEPARATOR _LINE_ _FILE_ _DATE_ _PRO_FILE_ Absolute path to .pro file in canonical format(.ie using '/' path separator) _PRO_FILE_PWD_ Absolute path to directory containing .pro file in canonical format(.ie using '/' path separator) _QMAKE_CACHE_ TEMPLATE QMAKE_HOST.os QMAKE_HOST.name QMAKE_HOST.version QMAKE_HOST.version_string QMAKE_HOST.arch QMAKE_DIR_SEP if not overriden defaults to DIR_SEPARATOR

Reference

BUILD_PASS

Set to the value of the current build pass. When processing the BUILDS variable.

BUILD_NAME

Set to the name of the build pass which is the contents of $${$${BUILD_PASS}.name} if defined otherwise, $$BUILD_PASS.

MAKEFILE_GENERATOR Specifies which generator backend to use for writing the output file.

Valid values are

Value C++ Generator Class
UNIX UnixMakefileGenerator
MINGW MingwMakefileGenerator
PROJECTBUILDER ProjectBuilderMakefileGenerator
XCODE ProjectBuilderMakefileGenerator
MSVC DspMakefileGenerator or NmakeMakefileGenerator
MSVC.NET VcprojGenerator or NmakeMakefileGenerator
BMAKE BorlandMakefileGenerator

Specified in the makespec's qmake.conf file.


TARGET

name of target. Depending on platform and TEMPLATE the actual target in the makefile may have lib prepended and TARGET_VERSION_EXT appended. Extensions are always handled by QMAKE. ie. can't generate a shared library as a ._pyd file.

TARGET_VERSION_EXT

  • defaults to $$VER_MAJ if defined
  • msvc_nmake generate cleans $(DESTDIR)$(TARGET)$(TARGET_VERSION_EXT).xxx

VERSION

  • major.minor.patch numbers
  • Used to define VER_MAJ and VER_MIN
  • msvc_nmake generator adds /VERSION:major.minor to link flags if !empty
  • msvc_vcproj generate adds /VERSION:major.minor to link flags and MSVCPROJ_VERSION if !empty
  • unixmake generate defines it to be 1.0.0 if not defined.

PRE_TARGETDEPS

list of targets to build before $(OBJECTS)

POST_TARGETDEPS

list of targets to build after $(OBJECTS)

QMAKE_POST_LINK

string added to end of $(DESTDIR_TARGET)

ALL_DEPS

targets to build after makefile and before $(DESTDIR_TARGET)


Finding files in VPATH

vpath uses is VPATH, QMAKE_ABSOLUTE_SOURCE_PATH, DEPENDPATH. Can't match wildcards using vpath, uses current directory of script.


Shadow builds

QMAKE_ABSOLUTE_SOURCE_ROOT : var QMAKE_ABSOLUTE_SOURCE_PATH : var Requires cache file. Current .pro file starts with cache file directory and .pro file does not start with the QMAKE_ABSOLUTE_SOURCE_ROOT then QMAKE_ABSOLUTE_SOURCE_PATH is QMAKE_ABSOLUTE_SOURCE_ROOT/relative path from cache directory.


LIBS

Variable contains a list of lib directories and lib names. /LIBPATH:xx is passed directly on in windows -L and /L adds directories -l and /l adds a library. If a highest version library is found in any of the previous -L directories then it is added with an optional suffix from QMAKE_{libname_in_uppercase}_SUFFIX. Otherwise the lib is added as is. -lfred would add fred.lib under windows if fred Finding highest version. Ignored if prl found and it specificies static lib. QMAKE_{libname_in_uppercase}_VERSION_OVERRIDE can contain a single integer. unless CONFIG contains 'no_versionlink' extra version number from: (lib)?{libname}(\d*).(dll|prl) if prl file contains QMAKE_PRL_VERSION check if it is bigger than found version. if QMAKE_{libname_in_uppercase}_SUFFIX exists it is added to the library name when searching. Note that if the lib file is not found on disk then the original libname.lib is used. This matching is useless for libs generated in one project being used in another as the dependee doesn't exist on disk at the time qmake generates the makefiles.


Multiple commands

$$escape_expand(\n\t) works for all generators. Commands will be joined by "&&" in vcproj files. The vcproj generator will map "\n\h" to newlines in vcproj files, no other generator understands '\h'


Visual Studio Project Generation

The command line qmake -spec win32-msvc2008 -tp vc -r will recursively create solution and project files from qmake project files. subdirs templates map to .sln files. By default the CONFIG variable contains 'flat' which flattens all files under their filter. Remove this to create a hierarchy of files matching their directory structure. Extra filter can be created from extra compilers.

Project dependencies

All .pro files are loaded with no build_pass variable defined. The QMAKE_ORIG_TARGET is used as the basename for the vcproj file. This is the TARGET variable before it is changed to reflect target on disk due to version numbers. The LIBS variable is scanned for libraries and these are used to match dependencies between projects.

prl files

If the CONFIG variable contains create_prl and qmake is generating a makefile or prl file () and QMAKE_FAILED_REQUIREMENTS is empty and the TEMPLATE is lib or vclib and config doesn't contain 'plugin' then a prl file is created at qmake time. The prl file name is the first non-empty contents of TARGET_PRL, TARGET. If the variable contains a path then the path is removed, and if there filename doesn't end with '.prl' then any characters after the left-most '.' character are removed and .prl appended. If QMAKE_BUNDLE is non-empty then QMAKE_BUNDLE(a directory path) is prepended. If DESTDIR is defined then it is prepended. If the path is relative then it is made absolute using the cwd. The file is written and the prl file path is added to ALL_DEPS and QMAKE_INTERNAL_PRL_FILE

The contents of the PRL_FILE consists of: QMAKE_PRL_BUILD_DIR The current directory or the directory portion of the -o option passed

   to qmake.

QMAKE_PRO_INPUT The name of the project file if it is not empty or '-'. QMAKE_PRL_SOURCE_DIR first item in QMAKE_ABSOLUTE_SOURCE_PATH if not empty. QMAKE_PRL_TARGET First value of TARGET as a filename. QMAKE_PRL_DEFINES Contents of PRL_EXPORT_DEFINES if non-empty. QMAKE_PRL_CFLAGS Contents of PRL_EXPORT_CFLAGS if non-empty. QMAKE_PRL_CXXFLAGS Contents of PRL_EXPORT_CXXFLAGS if non-empty. QMAKE_PRL_CONFIG Contents of CONFIG if non-empty. QMAKE_PRL_VERSION Contents of first item in TARGET_VERSION_EXT if non-empty,

   otherwise contents if VERSION if non-empty.

QMAKE_PRL_LIBS only when CONFIG contains staticlib or explicitlib. The contents

   is the contents of the variables listed in QMAKE_INTERNAL_PRL_LIBS otherwise
   QMAKE_LIBS.

QMAKE_INTERNAL_PRL_LIBS The Unix makefile generator appends [QMAKE_LIBDIR_FLAGS QMAKE_FRAMEWORKPATH_FLAGS QMAKE_LIBS]; msvc_dsp append [MSVCDSP_LIBS]

A prl file can have a type such as pkgconf, libtool, qmake. The CONFIG options no_read_prl_<type> stops processing of those types of prl files.

prl variable processing. QMAKE_PRL_LIBS - contents *= to QMAKE_INTERNAL_PRL_LIBS if non-empty otherwise QMAKE_LIBS. QMAKE_PRL_DEFINES - contents added to DEFINES if not in DEFINESor PRL_EXPORT_DEFINES. QMAKE_PRL_TARGET - file


Parsing

Scripts are parsed line by line. The line is stripped of trailing comments and line continuations are processed. The line is then simplified by remove leading, trailing and multiple white space characters. This means that you cannot define strings with multiple white space characters.

Splitting arguments to functions

Arguments to replace and test functions are parsed in the following way. Given a string containing the contents within parentheses of the function.

  1. Whitespace is removed from the start and end of the string.
  2. An open parentheses is matched with a closing one.
  3. An opening single or double quote is matched with its closing quote. The quotes are retained.
  4. A comma or end of string marks the end of the parameter, any white-space at the start or end is trimmed.

Splitting a value list

A value list is constructed from a string by:

  1. An escaped single or double quote is itself.
  2. Single, double quotes and parentheses are balanced.
  3. backslashes are retained.
  4. A space character marks the end of a value.

Variable expansion

The variable expansion of a string returns a list of strings. A function identifier is matched by the regular expression [a-zA-Z0-9._]

  • $$functionidentifer( and $${functionidentifier( indicate a replace function call. The parentheses are balanced and the contents inside the parentheses are split as an argument list with each argument undergoing variable expansion before being passed to the function named by functionidentifier as a list of list of strings.
  • $$functionidentifer and $${functionidentifer} are looked up in the symbol table.
  • $$[identifier] is looked up as a builin property.
  • $$(identifier) is looked up as an environment variable which is split as a value list.
  • A backslash followed by one of "[]{}()$\'" is itself.
  • Expansion within quotes is pasted as a string joined by spaces.
  • If single or double quotes are closed, a space or a tab character marks the end of a value. An empty value is ignored.

CONFIG values uses by makefile generation

link_prl precompile_header dll depend_includepath no_include_pwd qmake_cache build_pass no_read_prl_{libname_in_lowercase} staticlib explicitlib build_all no_autoqmake create_prl plugin copy_dir_files debug nostrip object_with_source no_delete_multiple_files subdir_first_pro ordered cd_change_global no_empty_targets

   makefile targets which would be empty have "@cd ." as their command

no_fixpath qt_dll console shared static no_batch autogen_precompile_source flat warn_off warn_on windows sdk generate_pbxbuild_makefile bundle app_bindle lib_bundle x86 ppc ppc64 x86_64 no_pb_munge_key rpath_libdirs macx GNUmake compile_libtool icc_pch_style objective_c no_smart_library_merge no_lflags_merge create_libtool create_pc no_sed_meta_install incremental echo_depend_creation no_dist_version no_plugin_name_prefix lib_version_first absolute_library_soname plugin_no_share_shlib_flags plugin_with_soname no_versionlink no_generated_target_info no_install_prl

Builtin CONFIG value tests

true Always true false Always false unix true when target is macx, qnx6 or unix macx true when target is macx qnx6 true when target is qnx6 mac9 true when target is mac9 mac true when target is mac9 or macx win32 true when target is win32 makespec true when matches filename of makespec


Problems with QMake

  • Incorrect handling of quoting/spaces in paths with environment varables.

File paths are, in places, unescaped(MakefileGenerator::unescapeFilePath) removing quotes and then escaped by wrapping in double quotes if there is a space in the filepath. The problem occurs if the filepath contains an environment variable refererence which contains a space at make-time. There is no way to quote this correctly an so using paths with spaces is broken. This applies to most everything.

  • Not handling QStringList variables appropriately with spaces. There are places

in the code where a QMake variable(which is a QStringList) is joined and then split on a ' '. This breaks when the values in the QStringList contains a space. This occurs when passing

  • Dependencies from an executed dependency command cannot contain a space. The

result of the depends command is joined with spaces and then simplified which collapses multiple white space characters.

  • OUT_PWD has a different value when a project is parsed recursively. When a subdirs

template project is parsed, each project in a subdirectory is parsed with the OUT_PWD containing a trailing slash. The first project parsed doesn't have the trailing slash. This makes a difference to the include_source_dir feature which compares OUT_PWD with _PRO_FILE_PWD_ to determine if it needs to add . to the INCLUDEPATH.

QTScript

use include(filename.js) All QMake test and replace functions are available from QTScript. All QTScript functions are available to QMake script code. QMake QStringList variables are flattened to a string when passed to QTScript. This means you need to join them with a magic separater and split them in QTScript if you want to preserve the list. As you would if you have a space in one of the QStrings. myScriptFunc($$join(varname,|))

function myScriptFunc(a)
{
    var arg_array = a.split('|');
}

QTScript functions must return a string array.

QMake variables are available through the qmake object. ie. qmake.CONFIG or qmake['CONFIG'] Note that the state of qmake can be stale so if you need to access any variables make sure you call any QMake function so that the qmake object is refreshed.

QMake Versions

Source is from [1].

2.10a Qt4.7.1
2.01a Qt4.4.1   (c)1992-2008
1.07a Qt3.3.8   (c)1992-2007
1.07a Qt3.3.7   (c)1992-2005
1.07a Qt3.3.6   (c)1992-2005
1.07a Qt3.3.5   (c)1992-2005
1.07a Qt3.3.4   (c)1992-2003
1.07a Qt3.3.3   (c)1992-2003
1.07a Qt3.3.2   (c)1992-2003
1.07a Qt3.3.1   (c)1992-2003
1.07a Qt3.3.0   (c)1992-2003
1.06c Qt3.2.3   (c)1992-2003
1.06c Qt3.2.2   (c)1992-2003
1.06c Qt3.2.1   (c)1992-2003
1.06c Qt3.2.0   (c)1992-2003
1.05a Qt3.1.2   (c)1992-2000
1.04a Qt3.1.1   (c)1992-2000
1.04a Qt3.1.0   (c)1992-2000
1.03a Qt3.0.6   (c)1992-2000
1.03a Qt3.0.5   (c)1992-2000
1.02a Qt3.0.4   (c)1992-2000
1.02a Qt3.0.3   (c)1992-2000
1.02a Qt3.0.2   (c)1992-2000
1.01a Qt3.0.1   (c)1992-2000
1.00a Qt3.0.0   (c)1992-2000


Variables used for makefile generation

CLEAN_DEPS list of targets to add to clean target. Not modified by backend. OBJECTS list of object files.

   Deleted in clean target.

QMAKE_CLEAN list of files to delete in clean target.

   nmake backend adds DESTDIR/TARGET{version}.{exp,pdb,ilk}, vc*.{pdb,idb}, pch file.

CLEAN_FILES list of filed to delete in clean target. Not modified by backends. QMAKE_DIST_CLEAN list of filed to delete in distclean target. No modified by backends.

Notes and references

Template:Reflist

External links

Personal tools