# Custom compiler for qface: # # If building a module, use load(ifcodegen_qt_module) instead # # Example input: # IFCODEGEN_SOURCES += my.foo.qface [required] # IFCODEGEN_MODULE_NAME = my_module_name # IFCODEGEN_TEMPLATE = frontend (or backend, simulator... -- defaults to "frontend") # IFCODEGEN_OUTPUT_DIR = my_output_dir (defaults to current build dir) # IFCODEGEN_ANNOTATIONS += additional.yaml # IFCODEGEN_EXTRA_TEMPLATE_SEARCH_PATH += extra_template_folder # QT_FOR_CONFIG += interfaceframework interfaceframework-private isEmpty(IFCODEGEN_TEMPLATE): IFCODEGEN_TEMPLATE = frontend isEmpty(IFCODEGEN_OUTPUT_DIR): IFCODEGEN_OUTPUT_DIR = $$OUT_PWD isEmpty(IFCODEGEN_SOURCES): error("IFCODEGEN_SOURCES must be set!") !contains(IFCODEGEN_SOURCES, .+\\.qface$) { error("Invalid qface file provided: The file needs to end with .qface") } # See the win32 section, why this is needed win32-msvc*:!contains(CONFIG, debug_and_release) { error("The ifcodegen works only in the debug_and_release configuration on windows") } IFCODEGEN_PWD = $$dirname(IFCODEGEN_SOURCES) IFCODEGEN_ABS_PWD = $$absolute_path($$IFCODEGEN_PWD, $$_PRO_FILE_PWD_) IFCODEGEN_FILE = $$basename(IFCODEGEN_SOURCES) IFCODEGEN_BASE_NAME = $$replace(IFCODEGEN_FILE, .qface, ) IFCODEGEN_YAML = $$IFCODEGEN_ABS_PWD/$${IFCODEGEN_BASE_NAME}.yaml OTHER_FILES += $$IFCODEGEN_ABS_PWD/$$IFCODEGEN_FILE # The 'click' library used by the generator needs to have a utf8 locale setup. equals(QMAKE_HOST.os, Windows): ENV = chcp 65001 && else: ENV = LC_ALL="en_US.UTF-8" # Detect whether we are using the feature inside the interfaceframework repository VIRTUALENV_PATH = $$[QT_HOST_LIBEXECS]/ifcodegen/ifcodegen_venv INTERNAL_VIRTUALENV_PATH = $$QTIF_BUILD_ROOT/src/tools/ifcodegen/ifcodegen_venv IF_GENERATOR_PATH = $$[QT_HOST_LIBEXECS]/ifcodegen IF_TEMPLATE_PATH = $$[QT_INSTALL_DATA]/ifcodegen-templates # Try to use the internal virtualenv when building interfaceframework # Because of the two stage build of COIN, it might not exist, but the installed version should still be there !isEmpty(QTIF_BUILD_ROOT):exists($$INTERNAL_VIRTUALENV_PATH) { VIRTUALENV_PATH = $$INTERNAL_VIRTUALENV_PATH IF_GENERATOR_PATH = $$QTIF_ROOT/src/tools/ifcodegen IF_TEMPLATE_PATH = $$IF_GENERATOR_PATH/templates equals(QMAKE_HOST.os, Windows): ENV += set IFGENERATOR_CONFIG="$$system_path($$QTIF_BUILD_ROOT/src/tools/ifcodegen/.config)" && else: ENV += IFGENERATOR_CONFIG="$$system_path($$QTIF_BUILD_ROOT/src/tools/ifcodegen/.config)" } # Don't rely on the feature system as those are for the target Qt, but we need to know # the installed components in the host Qt. # Because this prf is installed, the ifcodegen itself should be installed as well and # we just need to know whether a virtualenv needs to be used or system-python exists($$VIRTUALENV_PATH) { equals(QMAKE_HOST.os, Windows) { PYTHON = $$VIRTUALENV_PATH/Scripts/python.exe _LIB_FOLDERS = $$files($$VIRTUALENV_PATH/lib/python*) _LIB_FOLDER = $$first(_LIB_FOLDERS) SITE_PACKAGES = $${_LIB_FOLDER}/site-packages # No space between the path and && otherwise python3 adds the space to the path ENV += set VIRTUAL_ENV=$$system_path($$VIRTUALENV_PATH)&& } else { PYTHON = $$VIRTUALENV_PATH/bin/python _LIB_FOLDERS = $$files($$VIRTUALENV_PATH/lib/python*) _LIB_FOLDER = $$first(_LIB_FOLDERS) SITE_PACKAGES = $${_LIB_FOLDER}/site-packages ENV += LD_LIBRARY_PATH="$$system_path($$VIRTUALENV_PATH/bin)" ENV += VIRTUAL_ENV=$$system_path($$VIRTUALENV_PATH) } } else { exists($$IF_GENERATOR_PATH/generate.py) { !isEmpty(QMAKE_PYTHON3_LOCATION) { PYTHON = $$QMAKE_PYTHON3_LOCATION !exists($$PYTHON) { PYTHON = $$[QT_HOST_BINS]/python3 equals(QMAKE_HOST.os, Windows): PYTHON = $${PYTHON}.exe warning("The Python binary in QMAKE_PYTHON3_LOCATION variable doesn't exist, falling back to use QT_HOST_BINS") } } else { PYTHON = python3 equals(QMAKE_HOST.os, Windows): PYTHON = $${PYTHON}.exe } } else { # compiled ifcodegen IF_GENERATOR = $$IF_GENERATOR_PATH equals(QMAKE_HOST.os, Windows): IF_GENERATOR = $${IF_GENERATOR_PATH}.exe IF_GENERATOR_BUILD_DEPENDENCY = $$IF_GENERATOR } } isEmpty(IF_GENERATOR) { IF_GENERATOR = $$system_quote($$PYTHON) $$IF_GENERATOR_PATH/generate.py IF_GENERATOR_BUILD_DEPENDENCY = $$IF_GENERATOR_PATH/generate.py } # Add the builtin templates as default search path IF_TEMPLATE_SEARCH_PATH = $$IF_TEMPLATE_PATH # Add the paths defined by the global variable for (SEARCH_PATH, QT_IFCODEGEN_TEMPLATE_SEARCH_PATH) { dir = $$absolute_path($$SEARCH_PATH, $$_PRO_FILE_PWD_) IF_TEMPLATE_SEARCH_PATH *= $$dir } # Add the paths defined by function argument for (SEARCH_PATH, IFCODEGEN_EXTRA_TEMPLATE_SEARCH_PATH) { dir = $$absolute_path($$SEARCH_PATH, $$_PRO_FILE_PWD_) IF_TEMPLATE_SEARCH_PATH *= $$dir } for (SEARCH_PATH, IF_TEMPLATE_SEARCH_PATH) { IF_TEMPLATE_SEARCH_PATH_OPTIONS += -T $$system_quote($$system_path($$SEARCH_PATH)) } # TODO make this work with multiple input files, or only support one IFCODEGEN_SOURCE # Although this could be extra_compiler it is a normal EXTRA_TARGET for a reason. # In the debug_and_release configuration, we want to have the generator executed # during the run of the meta Makefile to only generate the code once. PRI = $$IFCODEGEN_OUTPUT_DIR/$$lower($${IFCODEGEN_BASE_NAME}).pri IF_GENERATOR_OPTIONS = $$IF_TEMPLATE_SEARCH_PATH_OPTIONS --template=$$IFCODEGEN_TEMPLATE --force !isEmpty(IFCODEGEN_MODULE_NAME): IF_GENERATOR_OPTIONS += --module=$${IFCODEGEN_MODULE_NAME} for (ANNOTATION, IFCODEGEN_ANNOTATIONS) { file = $$absolute_path($$ANNOTATION, $$_PRO_FILE_PWD_) IF_GENERATOR_OPTIONS += -A $$system_quote($$system_path($$file)) ifcodegen_sources.depends += $$file OTHER_FILES += $$file } for (IMPORT, IFCODEGEN_IMPORT_PATH) { dir = $$absolute_path($$IMPORT, $$_PRO_FILE_PWD_) IF_GENERATOR_OPTIONS += -I $$system_quote($$system_path($$dir)) } # Windows doesn't offer any other way to sleep for a time inside non-interactive scripts equals(QMAKE_HOST.os, Windows): { SLEEP = ping -n 2 127.0.0.1 >nul TOUCH = type nul > } else { SLEEP = sleep 1 TOUCH = touch } ifcodegen_sources.target = $$relative_path(.stamp-ifcodegen, $$OUT_PWD) ifcodegen_sources.commands += $(DEL_FILE) $$system_quote($$system_path($$OUT_PWD/.stamp-ifcodegen)) && ifcodegen_sources.commands += $$SLEEP && $$ENV $$system_path($$IF_GENERATOR) $$IF_GENERATOR_OPTIONS $$system_quote($$system_path($$IFCODEGEN_ABS_PWD/$${IFCODEGEN_FILE})) $$system_quote($$system_path($$IFCODEGEN_OUTPUT_DIR)) && ifcodegen_sources.commands += $$TOUCH $$system_quote($$system_path($$OUT_PWD/.stamp-ifcodegen)) ifcodegen_sources.depends = $$IF_GENERATOR_BUILD_DEPENDENCY ifcodegen_sources.depends += $$IFCODEGEN_ABS_PWD/$${IFCODEGEN_FILE} ifcodegen_sources.depends += $$files($$IF_TEMPLATE_PATH/common/*) QMAKE_CLEAN += $$relative_path(.stamp-ifcodegen, $$OUT_PWD) # Find the used templates within the search path FOUND_TEMPLATE = 0 for (SEARCH_PATH, IF_TEMPLATE_SEARCH_PATH) { IFCODEGEN_TEMPLATE_PWD = $$SEARCH_PATH/$${IFCODEGEN_TEMPLATE} exists($$IFCODEGEN_TEMPLATE_PWD) { ifcodegen_sources.depends += $$files($${IFCODEGEN_TEMPLATE_PWD}/*) FOUND_TEMPLATE = 1 break() } } # We didn't find the template in the search path, check whether it's a path to a template equals(FOUND_TEMPLATE, 0): { exists($${IFCODEGEN_TEMPLATE}) { ifcodegen_sources.depends += $$files($${IFCODEGEN_TEMPLATE}/*) } else { error("Invalid IFCODEGEN_TEMPLATE: Couldn't find the template: $$IFCODEGEN_TEMPLATE") } } # Add the configuration yaml as dependency and to other files exists($$IFCODEGEN_YAML) { ifcodegen_sources.depends += $$IFCODEGEN_YAML OTHER_FILES += $$IFCODEGEN_YAML } !isEmpty(IFCODEGEN_HEADERS_OUTPUT_DIR) { IFCODEGEN_HEADERS_OUTPUT_TARGET = $${IFCODEGEN_HEADERS_OUTPUT_DIR}/$$lower($${IFCODEGEN_MODULE_NAME})module.h ifcodegen_headers.target = $$relative_path($$IFCODEGEN_HEADERS_OUTPUT_TARGET, $$OUT_PWD) ifcodegen_headers.commands = $${QMAKE_COPY_FILE} $${IFCODEGEN_OUTPUT_DIR}/*.h $${IFCODEGEN_HEADERS_OUTPUT_DIR} ifcodegen_headers.depends = $$relative_path(.stamp-ifcodegen, $$OUT_PWD) $$IF_GENERATOR_BUILD_DEPENDENCY } # Reevaluate the Makefile after the generation has finished Makefile.target = Makefile # The relative_path is needed here as qmake will use a relative_path for the output files # when using a QMAKE_EXTRA_COMPILER Makefile.depends = $$relative_path(.stamp-ifcodegen, $$OUT_PWD) # Make the qmake_all target work for usage inside QtCreator # Because of the Makefile target the generator is called before the actual Makefile # is evaluated. This is a problem if the virtualenv is not created yet. # In this case we create the target with a dependency to the forceRebuild file. # This file is created during the qmake run and updated once the virtualenv is ready # and will then cause a rerun of qmake # When using qface from the system, we don't need to wait for the virtualenv to be setup QT_FOR_CONFIG *= interfaceframework-private !qtConfig(system-qface):!isEmpty(QTIF_BUILD_ROOT):!exists($$VIRTUALENV_PATH): { Makefile.depends = $$shadowed($$IF_GENERATOR_PATH)/forceRebuild } else { !isEmpty(IFCODEGEN_HEADERS_OUTPUT_TARGET) { Makefile.depends += $$relative_path($$IFCODEGEN_HEADERS_OUTPUT_TARGET, $$OUT_PWD) QMAKE_EXTRA_TARGETS += ifcodegen_headers } } # After the generation, this should exists and qmake can create the correct build tree exists($$PRI) { # save the state and reset for SOURCES, HEADERS and OTHER_FILES # Afterwards add all autogenerated files to the 'make clean' target SOURCES_ORIG = $$SOURCES SOURCES = HEADERS_ORIG = $$HEADERS HEADERS = OTHER_FILES_ORIG = $$OTHER_FILES OTHER_FILES = include($$PRI) QMAKE_CLEAN += $$SOURCES QMAKE_CLEAN += $$HEADERS QMAKE_CLEAN += $$OTHER_FILES QMAKE_CLEAN += $$PRI SOURCES += $$SOURCES_ORIG HEADERS += $$HEADERS_ORIG OTHER_FILES += $$OTHER_FILES_ORIG } QMAKE_EXTRA_TARGETS += Makefile ifcodegen_sources # NMAKE doesn't support the Makefile target to call qmake and reevaluate itself # Because of that, the autogeneration is not started at all and if started # qmake is not run and the Makefile revaluated... # To workaround this, we depend on debug_and_release as a meta Makefile is generated # where we can envorce the run of the generator and qmake. # Afterwards the sub makefiles are read (Makefile.debug/release), which have been # regenerated before starting NMAKE on them. win32-msvc* { qmake.depends = $$relative_path(.stamp-ifcodegen, $$OUT_PWD) debug.depends = qmake debug-make_first.depends = qmake debug-all.depends = qmake release.depends = qmake release-make_first.depends = qmake release-all.depends = qmake QMAKE_EXTRA_TARGETS += debug debug-make_first debug-all \ release release-make_first release-all \ qmake }