klayout/scripts/mkqtdecl.sh

293 lines
7.1 KiB
Bash
Executable File

#!/bin/bash -e
#
# A script to produce the Qt declaration files
#
# This script utilizes the extraction framework from mkqtdecl_common. The extraction
# framework is based on a C++ parser and a configuration file that specifies details
# about the translation.
#
# By default, the script will take the Qt headers from /opt/qt/4.6.3, /opt/qt/5.5.1
# and /opt/qt/6.2.1 for Qt4, Qt5 and Qt6 respectively.
#
# Call it from project level as
#
# ./scripts/mkqtdecl.sh -update # Qt4
# ./scripts/mkqtdecl.sh -update -qt5 # Qt5
# ./scripts/mkqtdecl.sh -update -qt6 # Qt6
#
# For more options see
#
# ./scripts/mkqtdecl.sh -h
#
#
# Copyright (C) 2006-2025 Matthias Koefferlein
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
dry=0
sync=0
update=0
diff=0
reuse=0
qt="/opt/qt/4.6.3/include"
qt5="/opt/qt/5.12.12/include"
qt6="/opt/qt/6.2.1/include"
inst_dir_common=`pwd`/scripts/mkqtdecl_common
inst_dir4=`pwd`/scripts/mkqtdecl4
inst_dir5=`pwd`/scripts/mkqtdecl5
inst_dir6=`pwd`/scripts/mkqtdecl6
src_dir=`pwd`/src
src_name4=gsiqt/qt4
src_name5=gsiqt/qt5
src_name6=gsiqt/qt6
qt_mods4="QtCore QtGui QtDesigner QtNetwork QtSql QtXml QtUiTools"
qt_mods5="QtCore QtGui QtWidgets QtDesigner QtNetwork QtPrintSupport QtSql QtSvg QtXml QtXmlPatterns QtMultimedia QtUiTools"
qt_mods6="QtCore QtGui QtWidgets QtNetwork QtPrintSupport QtSql QtSvg QtXml QtMultimedia QtUiTools QtCore5Compat"
src_name=$src_name4
inst_dir=$inst_dir4
qt_mods=$qt_mods4
work_dir="mkqtdecl.tmp"
while [ "$1" != "" ]; do
a="$1"
shift
case "$a" in
-h)
echo "Produce Qt declaration"
echo "Usage:"
echo " mkqtdecl.sh -update Produce and synchronize"
echo " mkqtdecl.sh -dry Dry run - produce, but don't synchronize"
echo " mkqtdecl.sh -sync Sync only - don't produce, but synchronize"
echo " mkqtdecl.sh -diff Show differences - don't produce and don't synchronize"
echo " mkqtdecl.sh -qt path_to_include Use the specified include path"
echo " mkqtdecl.sh -qt5 Use setup for Qt 5.x (use before -qt)"
echo " mkqtdecl.sh -qt6 Use setup for Qt 6.x (use before -qt)"
echo " mkqtdecl.sh -reuse Don't parse C++ container again"
exit 0
;;
-dry)
dry=1
;;
-sync)
sync=1
;;
-update)
update=1
;;
-diff)
diff=1
;;
-reuse)
reuse=1
;;
-qt)
qt="$1"
shift
;;
-qt5)
qt="$qt5"
work_dir="mkqtdecl5.tmp"
inst_dir="$inst_dir5"
qt_mods="$qt_mods5"
src_name="$src_name5"
;;
-qt6)
qt="$qt6"
work_dir="mkqtdecl6.tmp"
inst_dir="$inst_dir6"
qt_mods="$qt_mods6"
src_name="$src_name6"
;;
*)
echo "*** ERROR: unknown command option $a"
exit 1
;;
esac
done
if [ `expr $update + $sync + $dry + $diff` != 1 ]; then
echo "*** ERROR: either -update, -diff, -dry or -sync must be given"
exit 1
fi
# Production flags
# -diff -> update=0, dry=1
# -dry -> update=1, dry=1
# -sync -> update=0, dry=0
# -update -> update=1, dry=0
if [ $diff != 0 ]; then
dry=1
elif [ $dry != 0 ]; then
update=1
fi
if [ ! -e $src_dir ]; then
echo "*** ERROR: Source directory ($src_dir) not found - run script in repository root"
exit 1
fi
if [ ! -e $inst_dir ]; then
echo "*** ERROR: Installation path ($inst_dir) not found - run script in repository root"
exit 1
fi
if [ ! -e $inst_dir_common ]; then
echo "*** ERROR: Installation path ($inst_dir_common) not found - run script in repository root"
exit 1
fi
if ! ruby -v >/dev/null 2>&1; then
echo "*** ERROR: ruby not installed"
exit 1
fi
if ! ruby -e "require 'oj'" 2>&1; then
echo "*** ERROR: ruby gem 'oj' not installed"
exit 1
fi
if ! ruby -e "require 'treetop'" 2>&1; then
echo "*** ERROR: ruby gem 'treetop' not installed"
exit 1
fi
if [ $update != 0 ]; then
if [ -e $work_dir ] && [ $reuse == 0 ]; then
rm -rf $work_dir
fi
mkdir -p $work_dir
cd $work_dir
cp -R $inst_dir/Qt* .
for d in Qt*; do
cd $d
cp $inst_dir/{mkqtdecl.conf,mkqtdecl.properties,mkqtdecl.events} .
cp $inst_dir_common/{cpp_parser_classes.rb,cpp_classes.rb,c++.treetop,parse.rb,reader_ext.rb,produce.rb,common.conf} .
cd ..
done
if [ $reuse == 0 ]; then
for d in $qt_mods; do
echo "--------------------------------------------------------"
echo "Parsing $d ..."
echo ""
cd $d
echo "Running gcc preprocessor .."
# By using -D_GCC_LIMITS_H_ we make the gcc not include constants such as ULONG_MAX which will
# remain as such. This way the generated code is more generic.
gcc -std=c++17 -I$qt -fPIC -D_GCC_LIMITS_H_ -E -o allofqt.x allofqt.cpp
echo "Stripping hash lines .."
egrep -v '^#' <allofqt.x >allofqt.e
rm allofqt.x
echo "Parsing and producing db .."
./parse.rb -i allofqt.e -o allofqt.db
cd ..
done
fi
rm -f produced.txt
touch produced.txt
# Note the order of the modules is important: first modules get the
# classes first
for d in $qt_mods; do
echo "--------------------------------------------------------"
echo "Production on $d ..."
echo ""
cd $d
mkdir -p generated
echo "Producing code .."
./produce.rb -x ../produced.txt -i allofqt.db -m $d
# mark classes produced here as done
cat class_list.txt >>../produced.txt
cd ..
done
else
cd $work_dir
fi
for d in $qt_mods; do
echo "--------------------------------------------------------"
echo "Processing $d ..."
echo ""
cd $d
if [ ! -e generated ]; then
echo "*** ERROR: production output ("`pwd`"/generated) does not exist - production failed?"
exit 1
fi
cd generated
if [ $dry != 0 ]; then
echo "Synchronizing dry run .."
else
echo "Synchronizing .."
fi
count=0
for f in {*.cc,*.h} $d.pri; do
needs_update=0
if ! [ -e $src_dir/$src_name/$d/$f ]; then
echo "# INFO: creating new file $src_dir/$src_name/$f"
needs_update=1
elif ! cmp -s $f $src_dir/$src_name/$d/$f; then
echo "# INFO: out of date: syncing file $src_dir/$src_name/$f"
needs_update=1
fi
if [ $needs_update != 0 ]; then
count=`expr $count + 1`
if [ $dry != 0 ]; then
echo cp $f $src_dir/$src_name/$d/$f
else
echo === cp $f $src_dir/$src_name/$d/$f
cp $f $src_dir/$src_name/$d/$f
fi
fi
done
if [ $dry != 0 ]; then
echo "# INFO: $count files to synchronize"
else
echo "# INFO: $count files synchronized"
fi
cd ..
cd ..
done