#!/usr/bin/env bash # domake: # Compile U++ main tools: theide and umk ### Sourced file(s) . ./function_library ### Variables minimum_gcc_dumpversion="4.9.0" minimum_gcc_version=$(convert_version_to_number "$minimum_gcc_dumpversion") minimum_clang_dumpversion="3.4.0" minimum_clang_version=$(convert_version_to_number "$minimum_clang_dumpversion") show_debug_info="true" show_debug_warning="true" show_debug_error="true" use_gcc="false" use_clang="false" use_cpp_compiler="false" use_other_cpp_compiler="false" build_ide="true" build_umk="true" unset make_parameter_array ### Constants if [ -z "${DEFAULT_CXXFLAGS}" ]; then DEFAULT_CXXFLAGS="-O3 -ffunction-sections -fdata-sections" fi DEFAULT_GCC_CXXFLAGS=${DEFAULT_CXXFLAGS} DEFAULT_CLANG_CXXFLAGS="${DEFAULT_CXXFLAGS} -Wno-logical-op-parentheses" DEFAULT_CPP_CXXFLAGS=${DEFAULT_CXXFLAGS} DEFAULT_OTHER_CPP_CXXFLAGS=${DEFAULT_CXXFLAGS} EXIT_SUCCESS=0 EXIT_ERROR_COMMAND_LINE=1 EXIT_ERROR_NO_COMPILER_FOUND=2 EXIT_ERROR_NO_MAKE_FOUND=3 EXIT_ERROR_NO_IDE_FOUND=4 EXIT_ERROR_NO_UMK_FOUND=5 SCRIPT_NAME=$(basename "$0" | tr '[:lower:]' '[:upper:]' ) ### Function declarations show_usage() { echo 'Usage: ./domake [options]' echo echo 'Options:' echo ' ide : build theide only' echo ' umk : build umk only' echo ' --verbose : increase verbosity' echo ' --info=FLAGS : fine-grained informational verbosity ( default: true )' echo ' --warning=FLAGS : fine-grained warning verbosity ( default: true )' echo ' --debug=FLAGS : fine-grained debug verbosity ( default: true )' echo ' --help : show current usage information' echo echo 'Note:' echo ' * domake use environment variables to supersede auto generated variables and those from uppsrc/*Makefile.in:' echo ' - CXX : c++ compiler' echo ' - CXXFLAGS : c++ compiler flags' echo ' - CXXSTD : selected c++ mode (for -std value)' echo ' - NO_CXXSTD : do not add c++ mode to CXXFLAGS (disabled by default)' echo ' - UPPOUT : U++ output directory (full path)' echo " - CINC : default include directory list (use ';' as separator)" echo ' - Flags : U++ build flags (ex: +GUI,LINUX,POSIX,SHARED)' echo ' - LINKER : linker binary name' echo ' - LDFLAGS : linker extra flags' echo " - LIBPATH : library path list (use ';' as separator)" echo ' - AR : archive-maintaining program' echo echo 'Example: CXX=g++ Flags=+GUI,MT,GCC,SHARED,LINUX,POSIX UPPOUT="$HOME/tmp" ./domake' } # log_debug_info "Processing parameters" for arg in "$@" do case "$arg" in ide) build_ide="true" build_umk="false" ;; umk) build_ide="false" build_umk="true" ;; --verbose) show_debug_info="true" show_debug_warning="true" show_debug_error="true" ;; --info=*) show_debug_info=$( echo $arg | sed 's/--info=//' ) if [ "$show_debug_info" != "true" -a "$show_debug_info" != "false" ] then log_debug_error "Bad command line argument '$arg'" show_usage exit $EXIT_ERROR_COMMAND_LINE fi ;; --warning=*) show_debug_warning=$( echo $arg | sed 's/--warning=//' ) if [ "$show_debug_warning" != "true" -a "$show_debug_warning" != "false" ] then log_debug_error "Bad command line argument '$arg'" show_usage exit $EXIT_ERROR_COMMAND_LINE fi ;; --error=*) show_debug_error=$( echo $arg | sed 's/--error=//' ) if [ "$show_debug_error" != "true" -a "$show_debug_error" != "false" ] then log_debug_error "Bad command line argument '$arg'" show_usage exit $EXIT_ERROR_COMMAND_LINE fi ;; --help) show_usage exit $EXIT_SUCCESS ;; *) log_debug_error "Bad command line argument '$arg'" show_usage exit $EXIT_ERROR_COMMAND_LINE esac done ### Main script start here log_debug_info "Build ide = $build_ide" log_debug_info "Build umk = $build_umk" if which uname then platform=$(uname -s) log_debug_info "Detected system: $platform" case "$platform" in Darwin) if [ "$CXX" = "" ] # Force clang++ on Mac OS X (for now) then CXX="clang++" log_debug_info "Force CXX=$CXX for $platform" fi if [ "$Flags" = "" ] then Flags="+CLANG,NOGTK,GUI,MT,SHARED,OSX,POSIX" log_debug_info "Force Flags='$Flags' for $platform" fi ;; Linux) ;; MINGW*) ;; CYGWIN*) ;; GNU*) ;; *) esac fi if [ "$CXX" != "" ] then if [ "$(basename "$CXX")" = "g++" ] then log_debug_info "Will use g++ as requested" use_gcc="true" elif [ "$(basename "$CXX")" = "clang++" ] then log_debug_info "Will use clang++ as requested" use_clang="true" elif [ "$(basename "$CXX")" = "c++" ] then log_debug_info "Will use c++ as requested" use_cpp_compiler="true" else log_debug_info "Will use $CXX as requested" use_other_cpp_compiler="true" fi else log_debug_info "Searching for g++ compiler" if which g++ then log_debug_info "Found $(which g++)" gcc_dumpversion=$(gcc -dumpversion) gcc_version=$(convert_version_to_number "$gcc_dumpversion") if [ "$gcc_version" -ge "$minimum_gcc_version" ] then log_debug_info "g++ version: $gcc_dumpversion" use_gcc="true" CXX="g++" else log_debug_warning "The g++ compiler found (e.q $gcc_dumpversion) has a lower version than the minimum required version (e.q $minimum_gcc_dumpversion)" fi fi if [ "$use_gcc" = "false" ] then log_debug_info "Searching for clang++ compiler" if which clang++ then log_debug_info "Found $(which clang++)" clang_dumpversion=$(clang++ --version | grep -i version | grep -o -e '[[:digit:]][\.[:digit:]]*' | head -1) clang_version=$(convert_version_to_number "$clang_dumpversion") log_debug_info "clang++ version: $clang_dumpversion" use_clang="true" CXX="clang++" if [ "$clang_version" -lt "$minimum_clang_version" ] then log_debug_warning "The clang++ compiler found (e.q $clang_dumpversion) has a lower version than the minimum required version (e.q $minimum_clang_dumpversion)" fi else log_debug_info "Searching for a standard c++ compiler" if which c++ then log_debug_info "Found $(which c++)" log_debug_warning "This c++ compiler has not been tested yet. Compilation will perhaps fail" use_cpp_compiler="true" CXX="c++" c++ --version || true else log_debug_error "No compatible c++ compiler found in PATH" log_debug "${COLOR_WHITE}SOLUTIONS (a few):${COLOR_NC}" log_debug " - Install a compatible gcc-c++ version (> $minimum_gcc_dumpversion)" log_debug " - Or install clang++ LLVM compiler (> $minimum_clang_dumpversion)" log_debug " - Or add clang++ or g++ path to the PATH variable (if clang++ or a g++ compatible version is already installed)" exit $EXIT_ERROR_NO_COMPILER_FOUND fi fi fi fi CXXSTD_RE= #empty if [ -z "${NO_CXXSTD}" ]; then if [ "$platform" = "FreeBSD" ]; then CHECK_CXXSTD="c++14 c++1y c++11 c++0x" else CHECK_CXXSTD="c++14 c++11" fi if [ -z "${CXXSTD}" ]; then log_debug_info "Searching for supported C++ mode" for s in ${CHECK_CXXSTD}; do output=`${CXX} -std=${s} -c -x c++ /dev/null -o /dev/null 2>/dev/null && echo true` if [ "${output}" = "true" ]; then CXXSTD=${s} break fi done if [ -n "${CXXSTD}" ]; then log_debug_info "The -std=${CXXSTD} is supported by '${CXX}'" else log_debug_warning "The C++11 is not supported by '${CXX}'" fi fi if [ -n "${CXXSTD}" ]; then DEFAULT_GCC_CXXFLAGS="${DEFAULT_GCC_CXXFLAGS} -std=${CXXSTD}" DEFAULT_CLANG_CXXFLAGS="${DEFAULT_CLANG_CXXFLAGS} -std=${CXXSTD}" DEFAULT_CPP_CXXFLAGS="${DEFAULT_CPP_CXXFLAGS} -std=${CXXSTD}" DEFAULT_OTHER_CPP_CXXFLAGS="${DEFAULT_OTHER_CPP_CXXFLAGS} -std=${CXXSTD}" if [ -n "${CXXFLAGS}" ]; then CXXFLAGS="${CXXFLAGS} -std=${CXXSTD}" fi CXXSTD_RE="; /COMMON_CPP_OPTIONS/s|\(-std=\)[^\"[:blank:]]*|\1${CXXSTD}|" fi fi log_debug_info "Searching for extra make parameters" i=0 if [ "$CXXFLAGS" != "" ] then make_parameter_array[i++]="CXXFLAGS=$CXXFLAGS" elif [ "$use_gcc" = "true" -a "$DEFAULT_GCC_CXXFLAGS" != "" ] then make_parameter_array[i++]="CXXFLAGS=$DEFAULT_GCC_CXXFLAGS" elif [ "$use_clang" = "true" -a "$DEFAULT_CLANG_CXXFLAGS" != "" ] then make_parameter_array[i++]="CXXFLAGS=$DEFAULT_CLANG_CXXFLAGS" elif [ "$use_cpp_compiler" = "true" -a "$DEFAULT_CPP_CXXFLAGS" != "" ] then make_parameter_array[i++]="CXXFLAGS=$DEFAULT_CPP_CXXFLAGS" elif [ "$use_other_cpp_compiler" = "true" -a "$DEFAULT_OTHER_CPP_CXXFLAGS" != "" ] then make_parameter_array[i++]="CXXFLAGS=$DEFAULT_OTHER_CPP_CXXFLAGS" else log_debug_warning "CXXFLAGS environment variable not set. Will use the default value from uppsrc/*Makefile.in" fi if [ "$UPPOUT" != "" ] then make_parameter_array[i++]="UPPOUT=$UPPOUT" fi if [ "$CINC" != "" ] then make_parameter_array[i++]="CINC=$CINC" fi if [ "$Flags" != "" ] then make_parameter_array[i++]="Flags=$Flags" make_parameter_array[i++]="Macro=$(echo "$Flags" | sed -e 's|[[:space:]]*+[[:space:]]*|-Dflag|g' -e 's|[[:space:]]*,[[:space:]]*| -Dflag|g')" fi if [ "$LINKER" != "" ] then make_parameter_array[i++]="LINKER=$LINKER" fi if [ "$LDFLAGS" != "" ] then make_parameter_array[i++]="LDFLAGS=$LDFLAGS" fi if [ "$LIBPATH" != "" ] then make_parameter_array[i++]="LIBPATH=$LIBPATH" fi if [ "$AR" != "" ] then make_parameter_array[i++]="AR=$AR" fi if [ "${#make_parameter_array[@]}" != "0" ] then log_debug_info "Make parameters:" for (( i=0 ; i < ${#make_parameter_array[@]} ; i++ )) do log_debug_info " --> ${make_parameter_array[$i]}" done log_debug_info "Extra parameters will supersede default parameters" fi log_debug_info "Using pkg-config to find available libraries" if which pkg-config then if [[ "$Flags" = *"NOGTK"* ]] then requires_libraries="x11 libnotify freetype2" else requires_libraries="gtk+-3.0 x11 libnotify freetype2" fi library_list="" for i in $requires_libraries do if pkg-config --exists $i then library_list="$library_list $i" log_debug_info "pkg-config: Found library $i" else log_debug_warning "pkg-config: '$i' not found in $(pkg-config --variable pc_path pkg-config). Do you need to install $i development package?" fi done else log_debug_warning "Can't find pkg-config in PATH. Will do configuration without it. Compilation will probably fail" log_debug_warning "If compilation fail because of missing include, please install pkg-config before reporting" fi log_debug_info "Configuring" uppsrc/*Makefile.in library_list="" for i in uppsrc/*Makefile.in do # sed -e "s@-I((INCLUDES))@`pkg-config --cflags-only-I $library_list`@g" -e "s@-L\"((LIBRARIES))\"@`pkg-config --libs-only-L $library_list`@g" "$i" > "${i%.in}" cp -a "$i" "${i%.in}" done if [ "$platform" = "Darwin" ] then log_debug_info "Adjusting Makefiles for Mac OS X" sed -i.backup -E -e 's/(-Wl,[^[:space:]]*)//g' -e 's/-lrt//g' uppsrc/*Makefile fi if [[ "$Flags" = *"NOGTK"* ]] then log_debug_info "Removing references to GTK+" sed -i.backup \ -e 's/-lgtk-x11-3.0//g' \ -e 's/-lgdk-x11-3.0//g' \ -e 's/-latk-1.0//g' \ -e 's/-lgdk_pixbuf-2.0//g' \ -e 's/-lpangocairo-1.0//g' \ -e 's/-lpango-1.0//g' \ -e 's/-lgobject-2.0//g' \ -e 's/-lgmodule-2.0//g' \ -e 's/-lglib-2.0//g' \ -e 's/-lnotify//g' \ -e 's/`pkg-config --libs gtk+-3.0`//g' \ -e 's/`pkg-config --libs libnotify`//g' \ uppsrc/*Makefile fi if [ ! -f /usr/lib/libdl.so -a ! -f /usr/lib64/libdl.so ] then # We use sed -i.backup because Mac OS X sed version needs it (or it fails) sed -i.backup -e s/-ldl//g uppsrc/*Makefile fi # Cleanup rm -f uppsrc/*.backup log_debug_info "Searching for gmake or make" if which gmake then make_binary="gmake" elif which make then make_binary="make" else log_debug_error "No 'make' application found in PATH" exit $EXIT_ERROR_NO_MAKE_FOUND fi log_debug_info "Found $make_binary. Compiling..." if [ "${#make_parameter_array}" = "0" ] then if [ "$build_ide" = "true" ] then $make_binary -C uppsrc -e CXX="$CXX" fi if [ "$build_umk" = "true" ] then $make_binary -C uppsrc -e CXX="$CXX" -f uMakefile fi else if [ "$build_ide" = "true" ] then $make_binary -C uppsrc -e CXX="$CXX" "${make_parameter_array[@]}" fi if [ "$build_umk" = "true" ] # It doesn't matter if we define flags like GTK, NOGTK, X11 or GUI. umk is console based and won't use them. then $make_binary -C uppsrc -e CXX="$CXX" "${make_parameter_array[@]}" -f uMakefile fi fi if [ "$build_ide" = "true" ] then if [ -f "uppsrc/ide.out" ] then log_debug_info "Installing theide in current directory" cp -p "uppsrc/ide.out" ./theide else log_debug_warning "Can't find uppsrc/ide.out binary" exit $EXIT_ERROR_NO_IDE_FOUND fi fi if [ "$build_umk" = "true" ] then if [ -f "uppsrc/umk.out" ] then log_debug_info "Installing umk in current directory" cp -p "uppsrc/umk.out" ./umk else log_debug_warning "Can't find uppsrc/umk.out binary" exit $EXIT_ERROR_NO_UMK_FOUND fi fi exit $EXIT_SUCCESS