#! /bin/bash ## @file ## ## $Id$ ## ## $Date: 2004/08/31 15:57:19 $ ## $Author: marc $ ## ## @copy © Marc Wäckerlin ## @license LGPL, see file COPYING ## ## $Log: bootstrap.sh,v $ ## Revision 1.3 2004/08/31 15:57:19 marc ## added file header ## MY_NAME=${0##*/} PROJECT_PATH=$(pwd) DEFAULT_PROJECT_NAME=${PROJECT_PATH##*/} configure=0 build=0 docker=0 buildtarget="" overwrite=0 rebuild=0 novcs=0 excludevcs=() rebuildfiles=() while test $# -gt 0; do case "$1" in (--configure|-c) configure=1;; (--docker|-d) docker=1;; (--build|-b) configure=1; build=1; buildtarget+=" distcheck";; (--target|-t) shift; configure=1; build=1; buildtarget+=" $1";; (--clean) shift; configure=1; build=1; buildtarget+=" maintainer-clean";; (--overwrite|-o) overwrite=1;; (--rebuild|-r) rebuild=1;; (--rebuild-file|-f) shift; rebuildfiles+=("$1");; (--no-vcs|-n) novcs=1;; (--exclude-vcs|-x) shift; excludevcs+=("$1");; (--version|-v) echo "$Id$"; exit;; (--help|-h) less < same as -b, but specify target instead of distcheck --overwrite, -o overwrite all basic files (bootstrap.sh, m4-macros) --rebuild, -r force rebuild of generated files, even if modified --rebuild-file, -f rebild specific file (can be added multiple times) --no-vcs, -n do not automatically add files to version control --exclude-vcs, -x exclude specific file from version control --help, -h show this help --version, -v show version and date of this file DESCRIPTION Initializes your build environment, as far as neccessary. Reads your used features from configure.ac, if that file exists, or creates a configure.ac. Automatically copies or creates all required template files. From your new and empty project's subversion or git path, call $0 to initialize your build environment. Before you call ${MY_NAME} the very first time, edit ${0#/*}/AUTHORS and replace it with your name (or the authors of your project, one name each line, main developper and copyright holder on the first line). The first call to ${MY_NAME} should be something like ../bootstrap-build-environment/${MY_NAME} and not ./${MY_NAME}. Actually, you called $0. In the way you called ${MY_NAME}, it has detected ${DEFAULT_PROJECT_NAME} as the project name for your project in ${PROJECT_PATH}. In the first run, you should call ${MY_NAME} from a checked out the bootstrap-build-environment from https://dev.marc.waeckerlin.org/, and the path from where you call ${MY_NAME} (which is actually ${PROJECT_PATH}) should be the path to your newly created project. Please note that your project must be a checked out subversion or git repository, since this build environment relies on subversion or git. Example for an initial run, where your new projet is stored in subversion on https:/path/to/your/new-project: cd ~/svn svn co https://dev.marc.waeckerlin.org/svn/bootstrap-build-environment/trunk \\ bootstrap-build-environment svn co https:/path/to/your/new-project/trunk new-project cd new-project ../bootstrap-build-environment/bootstrap.sh Example for an initial run, where your new projet is stored in git on https:/path/to/your/new-project: cd ~/svn svn co https://dev.marc.waeckerlin.org/svn/bootstrap-build-environment/trunk \\ bootstrap-build-environment cd ~/git git clone https:/path/to/your/new-project cd new-project ../bootstrap-build-environment/bootstrap.sh RUNNING If you run ${MY_NAME}, it first generates the necessary files (see below), then first runs make distclean if a makefile exists. After this it calles aclocal, libtoolize, automake, autoconf and optionally ./configure. If necessary, files are added to version control. GENERATED FILES This script copies the following files into your project environment: * ${MY_NAME} * autogen.sh - just the basics to initialize auto tools and create configure * ax_init_standard_project.m4 - auxiliary macro definition file * ax_cxx_compile_stdcxx_11.m4 - auxiliary macro definition file * ax_check_qt.m4 - auxiliary macro definition file * resolve-debbuilddeps.sh - script to install debian package dependencies * resolve-rpmbuilddeps.sh - script to install RPM package dependencies * build-in-docker.sh - script to build the project encapsulated in a docker container * build-in-docker.conf - additional configuration for build-in-docker.sh * build-resource-file.sh - build resource.qrc file from a resource directory * sql-to-dot.sed - script to convert SQL schema files to graphviz dot in doxygen * mac-create-app-bundle.sh - script to create apple mac os-x app-bundle * test/runtests.sh - template file to run test scripts, i.e. docker based * AUTHORS - replace your name in AUTHORS before first run * NEWS - empty file add your project's news * README - add project description (first line is header, followed by an empty line) * configure.ac - global configuration file template * makefile.am - global makefile template * ${DEFAULT_PROJECT_NAME}.desktop.in - linux desktop file * src/makefile.am - if you enabled AX_USE_CXX * src/version.hxx - if you enabled AX_USE_CXX * src/version.cxx - if you enabled AX_USE_CXX * html/makefile.am - if you enabled AX_BUILD_HTML * scripts/makefile.am - if you enabled AX_USE_SCRIPTS * doc/makefile.am - if you enabled AX_USE_DOXYGEN * doc/doxyfile.in - if you enabled AX_USE_DOXYGEN * test/makefile.am - if you enabled AX_BUILD_TEST or AX_USE_CPPUNIT * examples/makefile.am - if you enabled AX_BUILD_EXAMPLES * debian/changelog.in - if you enabled AX_USE_DEBIAN_PACKAGING * debian/control.in - if you enabled AX_USE_DEBIAN_PACKAGING * debian/docs - if you enabled AX_USE_DEBIAN_PACKAGING * debian/${DEFAULT_PROJECT_NAME}.install - if you enabled AX_USE_DEBIAN_PACKAGING * debian/${DEFAULT_PROJECT_NAME}.dirs - if you enabled AX_USE_DEBIAN_PACKAGING * debian/${DEFAULT_PROJECT_NAME}-dev.install - if you enabled AX_USE_DEBIAN_PACKAGING * debian/${DEFAULT_PROJECT_NAME}-dev.dirs - if you enabled AX_USE_DEBIAN_PACKAGING * debian/rules - if you enabled AX_USE_DEBIAN_PACKAGING * debian/compat - if you enabled AX_USE_DEBIAN_PACKAGING * ${DEFAULT_PROJECT_NAME}.spec.in - if you enable AX_USE_RPM_PACKAGING * src/${DEFAULT_PROJECT_NAME}.pc.in - if you enabled AX_USE_LIBTOOL REBUILDING FILES To rebuild all these files, just run "${MY_NAME} -r". To copy only the files provided by this package, that means those files you must never change, that means to update the build system to the latest release, run "${MY_NAME} -o" You can also rebuild a list of singleany list of specific file files by adding option "${MY_NAME} -f " to rebuild file "". You can add option "-f" more than once. FILES TO EDIT After creation of the files, you can edit them according to your needs. Please don't forget to redo your edits after rebuilding a file. Most files don't even need to be edited, they work out of the box. The following files normally require editing: * AUTHORS * NEWS * README * configure.ac * src/makefile.am * html/makefile.am * test/makefile.am * examples/makefile.am FILE DEPENDENCIES You should rebuild (see above) the files, whenever you change the configuration a dependent, i.e.: * test/makefile.am depends on AX_USE_LIBTOOL * html/makefile.am depends on AX_BUILD_HTML * doc/doxyfile.in depends on AX_BUILD_EXAMPLES * debian/control.in depends on AX_USE_DOXYGEN, AX_USE_CPPUNIT AX_CXX_QT, AX_CHECK_QT, AX_REQUIRE_QT, AX_USE_LIBTOOL * debian/${DEFAULT_PROJECT_NAME}.install depends on AX_USE_LIBTOOL * debian/${DEFAULT_PROJECT_NAME}.dirs depends on AX_USE_LIBTOOL * debian/${DEFAULT_PROJECT_NAME}-dev.install depends on AX_USE_LIBTOOL * debian/${DEFAULT_PROJECT_NAME}-dev.dirs depends on AX_USE_LIBTOOL * ${DEFAULT_PROJECT_NAME}.spec.in depends on AX_USE_RPM_PACKAGING, AX_USE_LIBTOOL, AX_CHECK_QT, AX_REQUIRE_QT, AX_CXX_QT, AX_USE_CPPUNIT FILES * AUTHORS: First line is the main author and used in Debian and RPM packaging, so there must be a GPG key that matches to this line. * NEWS: File to add project news. * README: First line is a short description of your project, then an empty line must follow. All remaining lines are a long description of your project. this information is copied, e.g. in Debian or RPM packages. In C++ checking:\e[0m for version control system ..." VCS="" VCSDEPENDS="" if test -d .svn; then VCS="svn" VCSDEPENDS="subversion," echo -e " \e[32msuccess\e[0m detected ${VCS}" elif test -d .git; then VCS="git" VCSDEPENDS="git," echo -e " \e[32msuccess\e[0m detected ${VCS}" else echo -e " \e[33mignored\e[0m" fi HEADER='## @id '"\$Id\$"' ## ## This file has been added: ## - by '${MY_NAME}' ## - on '$(LANG= date +"%a, %d %B %Y %H:%M:%S %z")' ## Feel free to change it or even remove and rebuild it, up to your needs ## ## 1 2 3 4 5 6 7 8 ## 45678901234567890123456789012345678901234567890123456789012345678901234567890 ' CHEADER='/** @id '"\$Id\$"' This file has been added: - by '${MY_NAME}' - on '$(LANG= date +"%a, %d %B %Y %H:%M:%S %z")' */ // 1 2 3 4 5 6 7 8 // 45678901234567890123456789012345678901234567890123456789012345678901234567890 ' notice() { echo -e "\e[1;33m$*\e[0m" } run() { check=1 while test $# -gt 0; do case "$1" in (--no-check) check=0;; (*) break;; esac shift; done echo -en "\e[1m-> running:\e[0m $* ..." result=$($* 2>&1) res=$? if test $res -ne 0; then if test $check -eq 1; then echo -e " \e[31merror\e[0m" echo -e "\e[1m*** Failed with return code: $res\e[0m" if test -n "$result"; then echo "$result" fi exit 1 else echo -e " \e[33mignored\e[0m" fi else echo -e " \e[32msuccess\e[0m" fi } testtag() { local IFS="|" egrep -q '^ *'"($*)" configure.ac } contains() { local e for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done return 1 } checkdir() { if ! test -d "$1"; then # create path run mkdir -p "$1" if test -n "${VCS}" -a $novcs -eq 0 && ! contains "$1" "${excludevcs[@]}"; then run ${VCS} add "$1" fi fi } checkfile() { exists=0 if test -f "$1" -o -f "$1".in; then exists=1 fi test $exists -eq 1 } to() { mode="u=rw,g=rw,o=r" while test $# -gt 0; do case "$1" in (--condition) shift # test for a tag, abort if not set if ! testtag "$1"; then return 0 fi;; (--unless) shift # test for a tag, abort if set if testtag "$1"; then return 0 fi;; (--mode) shift # test for a tag, abort if not set mode="$1";; (*) break;; esac shift; done if checkfile "$1" && test $rebuild -eq 0 -o "$1" = "configure.ac" \ && ! contains "$1" "${rebuildfiles[@]}"; then # file already exists and must not be rebuilt return 1 fi checkdir "$(dirname ${1})" echo -en "\e[1m-> generating:\e[0m $1 ..." result=$(cat > "$1" 2>&1) res=$? if test $res -ne 0; then echo -e " \e[31merror\e[0m" echo -e "\e[1m*** Failed with return code: $res\e[0m" if test -n "$result"; then echo "$result" fi exit 1 else echo -e " \e[32msuccess\e[0m" fi run chmod $mode $1 if test $exists -eq 0; then if test -n "${VCS}" -a $novcs -eq 0 && ! contains "$1" "${excludevcs[@]}"; then run ${VCS} add "$1" if test "${VCS}" = "svn"; then run svn propset svn:keywords "Id" "$1" fi fi fi return 0 } copy() { if checkfile "$1" && test $overwrite -eq 0 \ && ! contains "$1" "${rebuildfiles[@]}"; then # file already exists and must not be rebuilt return fi local source="${0%/*}/$1" if ! test -r "${source}"; then source="../${source}" if ! test -r "${source}"; then source="${0%/*}/$1" fi fi run cp "${source}" "$1" if test $exists -eq 0; then if test -n "${VCS}" -a $novcs -eq 0 && ! contains "$1" "${excludevcs[@]}"; then run ${VCS} add "$1" if test "${VCS}" = "svn"; then run svn propset svn:keywords "Id" "$1" fi fi fi } doxyreplace() { echo -en "\e[1m-> doxyfile:\e[0m configure $1 ..." if sed -i 's|\(^'"$1"' *=\) *.*|\1'" $2"'|g' doc/doxyfile.in; then echo -e " \e[32msuccess\e[0m" else echo -e " \e[31merror\e[0m" echo -e "\e[1m**** command: $0 $*\e[0m" exit 1 fi } doxyadd() { echo -en "\e[1m-> doxyfile:\e[0m configure $1 ..." if sed -i '/^'"$1"' *=/a'"$1"' += '"$2" doc/doxyfile.in; then echo -e " \e[32msuccess\e[0m" else echo -e " \e[31merror\e[0m" echo -e "\e[1m**** command: $0 $*\e[0m" exit 1 fi } vcs2cl() { exists=0 if test -f "ChangeLog"; then exists=1 else touch "ChangeLog" fi if test -x $(which ${VCS}2cl); then if test "${VCS}" = "git"; then ${VCS}2cl > ChangeLog elif test -n "${VCS}"; then ${VCS}2cl fi fi if test $exists -eq 0; then if test -n "${VCS}" -a $novcs -eq 0 && ! contains "ChangeLog" "${excludevcs[@]}"; then run ${VCS} add ChangeLog fi fi } # Check if we are in subversion root, if so, create trunk, branches, tags: if test "${VCS}" = "svn" -a $novcs -eq 0; then if test "$(LANG= svn info | sed -n 's,Relative URL: *,,p')" = "^/"; then svn mkdir trunk branches tags cd trunk fi fi # Initialize the environment: copy ${MY_NAME} copy ax_init_standard_project.m4 copy ax_cxx_compile_stdcxx_11.m4 copy ax_check_qt.m4 copy resolve-debbuilddeps.sh copy resolve-rpmbuilddeps.sh copy build-in-docker.sh copy build-resource-file.sh copy sql-to-dot.sed copy mac-create-app-bundle.sh AUTHOR=$(gpg -K | sed -n 's,uid *,,p' | sort | head -1) if test -z "${AUTHOR}"; then AUTHOR="FIRSTNAME LASTNAME (URL) " fi to AUTHORS < #include #include #include int main(int argc, char *argv[]) try { QApplication a(argc, argv); QCommandLineParser parser; parser.addHelpOption(); parser.process(a); QStringList scripts(parser.positionalArguments()); ${PackageName} w; w.show(); return a.exec(); } catch (std::exception &x) { std::cerr<<"**** error: "< #include /// Main Window /** Main window for ${PACKAGE_NAME} */ class ${PackageName}: public QMainWindow, protected Ui::${PackageName} { Q_OBJECT; public: explicit ${PackageName}(QWidget *parent = 0): QMainWindow(parent) { setupUi(this); } virtual ~${PackageName}() {} }; #endif EOF to --condition AX_USE_CXX src/${PACKAGE_NAME}.ui < ${PackageName} 0 0 800 600 ${PackageName} 0 0 800 22 EOF to --condition AX_USE_CXX src/languages.qrc < ${PACKAGE_NAME}_de.qm ${PACKAGE_NAME}_fr.qm ${PACKAGE_NAME}_it.qm ${PACKAGE_NAME}_en.qm EOF fi to --condition AX_USE_CXX src/version.hxx < namespace NAMESPACE { /// get package string which consists of package name and package version std::string package_string(); /// get package name std::string package_name(); /// get package version std::string version(); /// get code build date std::string build_date(); /// get author, i.e. copyright holder std::string author(); /// get short package description (1st line of README) std::string description(); /// get long package description (starting at 3rd line in README) std::string readme(); /// get package logo file name std::string logo(); /// get package icon file name std::string icon(); /// used for what filename extern const std::string WHAT; /// used for ident filename extern const std::string IDENT; } EOF to --condition AX_USE_CXX src/version.cxx < namespace NAMESPACE { std::string package_string() { return PACKAGE_STRING; } std::string package_name() { return PACKAGE_NAME; } std::string version() { return PACKAGE_VERSION; } std::string build_date() { return BUILD_DATE; } std::string author() { return AUTHOR; } std::string description() { return DESCRIPTION; } std::string readme() { return README; } std::string logo() { return PACKAGE_LOGO; } std::string icon() { return PACKAGE_ICON; } const std::string WHAT("#(@) " PACKAGE_STRING); const std::string IDENT("\$Id: " PACKAGE_STRING); } EOF to --condition AX_USE_SCRIPTS scripts/makefile.am < ChangeLog";; esac) fi aclocal $(if testtag AX_USE_LIBTOOL; then echo libtoolize --force; fi) automake -a autoconf EOF to makefile.am<