📜 ⬆️ ⬇️

Qt / Objective-C ++ 11 or building a Qt project using GCC-4.7 and Clang

Good luck to everyone!

Today I will tell dear habrages about another perversion - about building a project written in Qt, under Mac OS X by the GCC-4.7.0 compiler with Clang impurity (about the hose - at the end of the article, it will become clear why ).

Why do we need GCC 4.7? Well, for example, to use all those cool features from the standard C ++ 11. Is this not enough? In addition to supporting the new standard, there are a lot of improvements in it compared to the GCC 4.2 bundled with Xcode (although it turns out to be i686-apple-darwin11-llvm-g ++ - 4.2), so the meaning of the transition to 4.7 is clearly there. But the problems are present, as described below.
')
We can assume that we will need some features from Cocoa , which means we will need the Objcetive-C compiler, and even better - Objective-C ++, for example, to integrate our Qt-application into the Mac OS X environment.

We will start with the installation of GCC-4.7.0. You can, of course, use the ready-made assembly (for example, from here ), but we will go the way of the Jedi and build the compilers themselves, because in the assembly by the link above there is no support for Objective-C [++]. It is simpler than it seems at first glance, you can do everything manually (following the instructions, for example, from here ), and you can make a normal script that will do all the work for us. For example, my script, based on this discussion , will require brew and wget:

 #!/bin/bash # # This script downloads and builds GCC 4.7.0 for Mac OS X. # Depends on: brew, wget # # This file is modifyed version of script by Konrad Rudolph, found here: # http://apple.stackexchange.com/questions/38222/how-do-i-install-gcc-via-homebrew # VERSION=4.7.0 VER_SHORT=4.7 PREFIX=/usr/local/gcc-${VER_SHORT} TEMP_DIR=temp-gcc LANGUAGES=c,c++,objc,obj-c++ MAKE='make -j 4' echo "Preparing to install GCC ${VERSION}..." echo " Installation path: ${PREFIX}" echo " Temporary dir: ${TEMP_DIR}" echo " Programming languages: ${LANGUAGES}" brew-path() { brew info $1 | head -n3 | tail -n1 | cut -d' ' -f1; } # Prerequisites echo echo "Installing gmp, mpfr and libmpc using brew..." brew install gmp brew install mpfr brew install libmpc # Download & install the latest GCC echo echo "Downloading GCC sources..." mkdir -p $PREFIX mkdir ${TEMP_DIR} cd ${TEMP_DIR} wget ftp://ftp.gnu.org/gnu/gcc/gcc-${VERSION}/gcc-${VERSION}.tar.gz tar xfz gcc-$VERSION.tar.gz rm gcc-${VERSION}.tar.gz cd gcc-${VERSION} mkdir build cd build echo echo "Configuring GCC..." ../configure \ --prefix=$PREFIX \ --with-gmp=$(brew-path gmp) \ --with-mpfr=$(brew-path mpfr) \ --with-mpc=$(brew-path libmpc) \ --program-suffix=-${VER_SHORT} \ --enable-languages=${LANGUAGES} \ --with-system-zlib \ --enable-stage1-checking \ --enable-plugin \ --enable-lto \ --disable-multilib echo echo "Building GCC..." $MAKE bootstrap echo echo "Installing GCC..." make install 
(its development can be monitored on the githab )

Well, after a half-hour (±) build, we get GCC 4.7.0, which is installed in /usr/local/gcc-4.7/bin. Now you can try to build our project with it. But first, just check if it works:

 $ export PATH=/usr/local/gcc-4.7/bin:$PATH $ g++-4.7 --version g++-4.7 (GCC) 4.7.0 Copyright (C) 2012 Free Software Foundation, Inc.     .      .   - ,       - . 

Well, not bad at all. But how to make qmake build a project with this compiler? In addition to the export PATH we will need to tell qmake which compiler to use. This can be done in two ways.

The first method, rough, crooked and uncomfortable, and most importantly - fundamentally wrong. Specify the compiler in the .pro file:

 macx { QMAKE_CXX = g++-4.7 QMAKE_CXXFLAGS += -std=c++11 -v QMAKE_CXXFLAGS_X86_64 -= -Xarch_x86_64 QMAKE_CC = gcc-4.7 QMAKE_CFLAGS += -std=c++11 -v QMAKE_CFLAGS_X86_64 -= -Xarch_x86_64 QMAKE_LINK = $$QMAKE_CXX QMAKE_LINK_SHLIB = $$QMAKE_CXX QMAKE_LINK_C = $$QMAKE_CC QMAKE_LINK_C_SHLIB = $$QMAKE_CC QMAKE_LFLAGS_X86_64 -= -Xarch_x86_64 QMAKE_OBJECTIVE_CFLAGS_X86_64 -= -Xarch_x86_64 } 

The second way, neat, beautiful and correct . Create your mkspec ! To do this, go to /usr/local/Qt4.8/mkspecs , and execute some simple commands to start with:

 sudo cp macx-g++ macx-g++47 sudo cp common/g++-base.conf common/g++47-base.conf sudo cp common/g++-macx.conf common/g++47-macx.conf 

Next, in our favorite text editor (in my case, mcedit), we bring the macx-g++47/qmake.conf to the following form:

 MAKEFILE_GENERATOR = UNIX TARGET_PLATFORM = macx TEMPLATE = app CONFIG += qt warn_on release app_bundle incremental global_init_link_order lib_version_first plugin_no_soname link_prl QT += core gui QMAKE_INCREMENTAL_STYLE = sublib include(../common/mac.conf) include(../common/gcc-base-macx.conf) include(../common/g++47-macx.conf) load(qt_config) 

In essence, we append “47” in the middle of the last but one line. Next, edit the file common/g++47-macx.conf , make it like this:

 include(g++47-base.conf) QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_DWARF2 QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_DWARF2 QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO += -g $$QMAKE_CFLAGS_DWARF2 QMAKE_LFLAGS_STATIC_LIB += -all_load QMAKE_CFLAGS_X86_64 += -mmacosx-version-min=10.5 -std=c++11 QMAKE_CFLAGS_PPC_64 += -mmacosx-version-min=10.5 -std=c++11 QMAKE_CXXFLAGS_X86_64 = $$QMAKE_CFLAGS_X86_64 QMAKE_CXXFLAGS_PPC_64 = $$QMAKE_CFLAGS_PPC_64 QMAKE_OBJECTIVE_CFLAGS_X86_64 = $$QMAKE_CFLAGS_X86_64 QMAKE_OBJECTIVE_CFLAGS_PPC_64 = $$QMAKE_CFLAGS_PPC_64 QMAKE_LFLAGS_X86_64 = $$QMAKE_CFLAGS_X86_64 QMAKE_LFLAGS_PPC_64 = $$QMAKE_CFLAGS_PPC_64 QMAKE_OBJCFLAGS_PRECOMPILE = -x objective-c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_OBJCFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE QMAKE_OBJCXXFLAGS_PRECOMPILE = -x objective-c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_OBJCXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE 

Again, in essence, we change only the build flags and add MAGIC NUMBER 47.

Now we finish g++47-base.conf :

 QMAKE_CC = gcc-4.7 QMAKE_LINK_C = $$QMAKE_CC QMAKE_LINK_C_SHLIB = $$QMAKE_CC QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -g QMAKE_CXX = g++-4.7 QMAKE_LINK = $$QMAKE_CXX QMAKE_LINK_SHLIB = $$QMAKE_CXX QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO QMAKE_PCH_OUTPUT_EXT = .gch QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE} QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE 

image Here we again added "-4.7" in a couple of lines. Well, that will be enough. Now you can customize Qt Creator to work with the new mkspec! In the settings, go to Build & Run -> Tool Chains -> Add -> GCC , in the Compiler path field enter /usr/local/gcc-4.7/bin/g++-4.7 , in the Debugger - /usr/bin/gdb , and mkspec - macx-g++47 . The toolchain itself can be called something like “GCC-4.7”, “c ++ 11 compiler” or something like that. Now you can choose our new toolchain in the project settings and - voila! - the project will be assembled by our freshly assembled compiler! If we want to use the whole thing from the console, it will be enough to call qmake with the -spec macx-g++47 parameter.

Well, you can work, projects are collected, run and work. But there are a couple of problems ...

More precisely, problem. One of them is if you try to start using Objective-C [++] in the project, then the compiler will be a little bent. Why? The reason is simple: the Objective-C compiler from GCC does not understand blocks! How so? Why? Who allowed? I do not know, but the fact is a fact. Therefore, it will be extremely confusing outside of C / C ++. It's a pity. But let's not lose heart! If Objective-C [++] code cannot be compiled using GCC, we will compile it with clang. To do this, again, edit the g++47-base.conf and g++47-macx.conf , g++47-macx.conf following lines to the end:

 # in file g++47-base.conf QMAKE_OBJECTIVE_CC = clang # in file g++47-macx.conf QMAKE_OBJECTIVE_CFLAGS += -std=c++0x -stdlib=libc++ 

Thus, all our C / C ++ sources will be built with g ++ - 4.7, and Objective-C sources [++] will be built with clang. Uncomfortable? Of course, uncomfortable! It would seem that it is easier to switch completely to clang, since it supports C ++ 11 in some volume. But! It’s still a long way from GCC, so in our * .mm files we’ll be careful not to use C ++ 11 in large quantities, the hose will not withstand everything, unfortunately. But in the * .cpp files there is a place to roam!

If you are reluctant to walk around mkcpecs and edit them, I ask for a github , there I posted my version. And remember! GCC 4.7 is installed in /usr/local/gcc-4.7/bin/ , so you cannot do without PATH export! Although, in Qt Creator you can add this path in the PATH for building in the project properties.

Successful builds! And fewer errors!

PS: If you find inaccuracies and / or know better methods, please unsubscribe in the comments =).

Source: https://habr.com/ru/post/144707/


All Articles