5.10.1 static build error

QT 2018. 3. 23. 15:07

5.7.1 에서는 안그랬다.


5.10.1 소스 다운 받아서 압축 풀고 configure 해주고 빌드를 시작하니

아래와 같은 에러가 뜨면서 qmake.exe 가 죽었다는 에러 창이 떴다.


ASSERT: "isAbsolutePath(baseDir)" in file C:/Qt/5.10.1/qtbase/qmake/library/ioutils.cpp, line 106


구글링 결과 configure 후에 생기는 qtbase/bin/qt.conf 파일의 path 들이

내 시스템(windows)에 맞게 되지 않고 linux 기준으로 작성되어 생기는 문제였다.


참고로 내 qt.conf 파일 내용은 아래와 같다.


[EffectivePaths]

Prefix=..

[DevicePaths]

Prefix=/usr/local/Qt-5.10.1

[Paths]

Prefix=/usr/local/Qt-5.10.1

HostPrefix=/usr/local/Qt-5.10.1

Sysroot=

SysrootifyPrefix=false

TargetSpec=win32-g++

HostSpec=win32-g++


굵게 표기된 3군데 경로를 아래와 같이 내 경로로 수정하였다.


[EffectivePaths]

Prefix=..

[DevicePaths]

Prefix=C:/Qt/5.10.1

[Paths]

Prefix=C:/Qt/5.10.1

HostPrefix=C:/Qt/5.10.1

Sysroot=

SysrootifyPrefix=false

TargetSpec=win32-g++

HostSpec=win32-g++


저장하고 다시 빌드를 하니 잘 돌아간다.


참고: http://www.qtcentre.org/threads/69198-ASSERT-quot-isAbsolutePath(baseDir)-quot-error-when-trying-to-build

'QT' 카테고리의 다른 글

버전 정보 넣기  (0) 2016.09.26
undefined reference to 'vtable for...'  (0) 2016.05.19
반투명 그릴 때 배경 잔상 문제  (0) 2016.05.11
libwinpthread 가 계속 동적 빌드만 될 때  (0) 2016.04.28
디버깅 매크로  (0) 2016.04.19
Posted by 독뽀
,

버전 정보 넣기

QT 2016. 9. 26. 17:00

<QT 4.8>


QCoreApplication 클래스에는 applicationVersion() 라는 static 메서드가 있습니다.

QString을 반환하는데요.. setApplicationVersion(QString) 을 해주지 않으면

빈 문자열을 반환합니다.


버전 정보를 직접 넣어줘야 한다는 이야기 인데요..

버전 정보를 *.h나 *.cpp에 넣으면 버전만 수정할 때 리비전이 보기 싫게 되는 경우가 생깁니다.


이럴 때를 위해서 코드에서 수정하기보다는..


*.pro 파일에서 DEFINES 키워드를 사용해서 추가하는 것을 권장합니다.

DEFINES 에 추가할 때는 그냥 따옴표를 붙여서는 안됩니다.

그냥 해보니 숫자로 인식하더군요..


ex) DEFINES += APP_VERSION="0.0.1"


위의 경우 아래와 같이 10진수에 소수점 표기가 너무 많다고 빌드 에러가 날겁니다.

-1: error: too many decimal points in number


이를 해결하기 위해서는 아래와 같이 하시면 됩니다.


ex) DEFINES += APP_VERSION=\\\"0.0.1\\\"


*.pro 파일에 대한 키워드 도움말을 보시면 VERSION 이라는 키워드가 있는데요,

이 키워드는 윈도우에서 파일 등록 정보를 볼 때 나타나는 버전 정보를 나타내는 문자열입니다.

결국 아래처럼 수정이 필요 했습니다.


ex) VERSION = 1.0.0 # 이 키워드는 1.0.0 을 그대로 인식하고 있습니다.

DEFINES += APP_VERSION=\\\"$$VERSION\\\" # \\\" 를 붙이지 않으면 역시 숫자로 인식


이후 main.cpp 의 main() 에 QCoreApplication::setApplicationVersion(APP_VERSION); 을 추가하면

QCoreApplication::applicationVersion() 으로 *.pro에 입력한 버전 정보를 가져올 수 있습니다.


VERSION 을 추가한 효과로 아래처럼 윈도우 등록 정보에서 버전 정보가 나타나게 됩니다.


덧붙여서 가능하면 qmake 클린 빌드를 해주세요.

*.pro 의 갱신이 제대로 안되는 경우가 발견이 되었습니다.


참고:

http://www.openguru.com/2009/11/qt-best-way-to-set-application-version.html



'QT' 카테고리의 다른 글

5.10.1 static build error  (2) 2018.03.23
undefined reference to 'vtable for...'  (0) 2016.05.19
반투명 그릴 때 배경 잔상 문제  (0) 2016.05.11
libwinpthread 가 계속 동적 빌드만 될 때  (0) 2016.04.28
디버깅 매크로  (0) 2016.04.19
Posted by 독뽀
,

undefined reference to 'vtable for...'


이런 에러가 뜨는 경우 두 가지를 먼저 살펴보시면 문제 해결을 빨리 할 수도 있습니다.


1. virtual 키워드 사용한 곳 찾기

 - 구현을 강제하려고 순수 가상 함수로 만들어 놓은 인터페이스가 있다면,

 1.1. 해당 인터페이스를 구현 하였는지

 1.2 순수 가상 함수가 아니라 virtual 키워드만 추가한 것은 아닌지

   - 참고: 순수 가상함수 원형

     virtual void slotPendingProcess() = 0;

     virtual void slotPendingProcess() { } // 이렇게 해도 무방


2. QT에서는 목적 파일(*.o) 외에 QT에서 제공하는 특수한

moc_*.o/moc_*.cpp (Meta-object compiler) 파일이 생성됩니다.


자세한 내용은 http://doc.qt.io/qt-5/moc.html 이 곳과

https://kldp.org/node/123913 의 답변을 참고해주세요.


의심 되는 부분을 수정 하였음에도 (항목 1이나 그 외 문법상 이상이 없다고 판단)

에러가 나는 경우에는 위에서 언급한 moc_*.o/moc_*.cpp 파일을 의심해 봐야합니다.

위 파일은 컴파일 단계에서 갱신이 안되거나, (F5를 통해 실행하려고 할 때)

파일 이름이나 클래스 이름이 바뀌었는데 moc 가 갱신이 안되었거나 하기도 합니다.


이런 경우 Makefile 를 갱신해 주어야 하는데요,

qt에서는 Makefile을 직접 작성하지 않죠, qmake 를 한 번 해주고

클린 빌드를 통해서 이를 해결 할 수 있습니다.


'QT' 카테고리의 다른 글

5.10.1 static build error  (2) 2018.03.23
버전 정보 넣기  (0) 2016.09.26
반투명 그릴 때 배경 잔상 문제  (0) 2016.05.11
libwinpthread 가 계속 동적 빌드만 될 때  (0) 2016.04.28
디버깅 매크로  (0) 2016.04.19
Posted by 독뽀
,

환경: QtCreator3.4.2 / mingw4.9.2 / Qt 4.8.6 static


반투명 배경을 가진 글자가 흐르는 자막 기능이 필요해서 구현 해 보았습니다.


간단히 쓰려는 글자의 크기를 알아내어 (QFontMetrics 참조)

그 크기에 맞게 QPixmap (mBuffer) 을 하나 생성해서


mBuffer = QPixmap(QFontMetrics(mFont).boundingRect(message).width() + 14, height()); // 14는 여백


QPainter를 이용해 글자를 쓰고,

QPainter painter(&mBuffer);

if (painter.isActive()) {

    painter.end();

}

painter.begin(&mBuffer);

painter.setFont(mFont);

painter.setRenderHint(QPainter::Antialiasing);


QRect bufferRect = mBuffer.rect();

painter.setPen(mTextColor);

painter.setBrush(Qt::NoBrush);


bufferRect.setY(bufferRect.y() + 20);

painter.drawText(bufferRect, Qt::AlignCenter, msg);

painter.end();

raise();

show();


startCaptionThread();  // 쓰레드 호출


QThread (혹은 QTimer) 등을 이용해서 그릴 위치인 QPoint 좌표의 x축만 이동 시킨 후 update() 를 호출하고,

const int textWidth = mBuffer.width();

if (-textWidth < mPos.x()) {

    mPos.setX(mPos.x() - 1);

    update();

} else {

    // 자막이 화면에서 완전히 사라진 상태, 자막 초기화

}


paintEvent 에서는 글자가 써진 QPixmap 을 그릴 위치인 QPoint 좌표대로 그리기만 합니다.

QPainter p(this);

if (p.isActive()) {

    p.end();

}

p.begin(this);

QRect r = mBuffer.rect();

r.setX(mPos.x());

p.drawPixmap(r.x(), r.y(), mBuffer);


p.end();


그런데 자막이 화면에서 사라지기 전에 자막을 다시 그리도록 재시작을 했더니

자막 배경에 이전에 보이던 글자들의 잔상이 남아있었습니다.


해결 방법은 간단했습니다.


QPixmap 에 글자를 쓰기 직전에 QPixmap 을 fill 메서드를 통해 투명으로 칠해 주었더니 해결되었습니다.

mBuffer.fill(Qt::transparent);


'QT' 카테고리의 다른 글

버전 정보 넣기  (0) 2016.09.26
undefined reference to 'vtable for...'  (0) 2016.05.19
libwinpthread 가 계속 동적 빌드만 될 때  (0) 2016.04.28
디버깅 매크로  (0) 2016.04.19
QByteArray 의 reserve() vs resize()  (0) 2016.03.18
Posted by 독뽀
,

환경: QtCreator3.4.2 / mingw4.9.2 / Qt 4.8.6 static


QThread 를 사용하고 정적 빌드를 하려니 libwinpthread 에 대한 의존성이 생겼나보다.


구글링을 해보니


http://stackoverflow.com/questions/13768515/how-to-do-static-linking-of-libwinpthread-1-dll-in-mingw


요약) -static -lpthread 붙여라


이 답변을 확인하게 되었는데,

막상 위 옵션을 QtCreator의 빌드 옵션에서 컴파일러 옵션에 넣어봤는데 도무지 동작하지가 않았다.

위 링크가 또 다른 여러 곳에서 링크되어 있는 것으로 봐서는 아마도 맞는 답변이지 싶은데 말이다.


컴파일 로그를 살펴보니 다음과 같았다.


...

g++ -static-libgcc -static-libstdc++ -Wl,-s -Wl,-subsystem,windows -o release\sample.exe object_script.trainer.Release  -L"c:\Qt\4.8.6_static\lib" -lmingw32 -lqtmain -lQtXml -lQtGui -lQtNetwork -lgdi32 -lcomdlg32 -loleaut32 -limm32 -lwinmm -lwinspool -lmsimg32 -lQtCore -lole32 -luuid -lws2_32 -ladvapi32 -lshell32 -luser32 -lkernel32


어라..? 내가 추가 한 -static -lpthread가 보이지 않았다.


여러가지 찾아 보다 알아낸 결과는 아래와 같다.


*.pro 파일 내에 사용할 라이브러리를 추가 한다.

LIBS += -static -lwinpthread


나같은 경우 위와 같이 추가하고 빌드한 결과 컴파일 로그에 다음과 같이 추가된 것을 확인할 수 있었다.


g++ -static-libgcc -static-libstdc++ -Wl,-s -Wl,-subsystem,windows -o release\sample.exe object_script.trainer.Release -L"c:\Qt\4.8.6_static\lib" -lmingw32 -lqtmain -static -lwinpthread -lQtXml -lQtGui -lQtNetwork -lgdi32 -lcomdlg32 -loleaut32 -limm32 -lwinmm -lwinspool -lmsimg32 -lQtCore -lole32 -luuid -lws2_32 -ladvapi32 -lshell32 -luser32 -lkernel32


release 시에만 추가하고 싶다면

release {

LIBS += -static -lwinpthread

}

요렇게 해주면 release 시에만 정적으로 추가하게 된다.

'QT' 카테고리의 다른 글

undefined reference to 'vtable for...'  (0) 2016.05.19
반투명 그릴 때 배경 잔상 문제  (0) 2016.05.11
디버깅 매크로  (0) 2016.04.19
QByteArray 의 reserve() vs resize()  (0) 2016.03.18
QT static build with mingw32  (0) 2015.09.17
Posted by 독뽀
,

디버깅 매크로

QT 2016. 4. 19. 15:42

[파일 명][함수:라인] 내용


이런 형식이 필요하여 만들었음.


2018.12.27 수정, 이전 버전은 UTF8 지원이 불가함 (한글 출력 안됨)

수정 버전 사용할 것을 추천..


#ifndef DEFINE_MACRO_H

#define DEFINE_MACRO_H


#include <QDebug>


#define ENTIRE_DEBUG_ON     1

#define DEBUG_VERBOSE       1


#if ENTIRE_DEBUG_ON

#if DEBUG_VERBOSE

#define VERBOSE() qDebug("[%s][%s:%d]", __FILE__, __func__, __LINE__)

#endif

#define DEBUG(MESSAGE) qDebug("[%s][%s:%d] %s", __FILE__, __func__, __LINE__, (MESSAGE))

#define SDEBUG(...) { \

    QString arg; \

    arg.sprintf(__VA_ARGS__); \

    qDebug() << QString("[%1][%2:%3]").arg(__FILE__).arg(__func__).arg(__LINE__) << arg.toUtf8(); \

}

#else

#define VERBOSE() ;

#define DEBUG(MESSAGE) ;

#define SDEBUG(...) ;

#endif


#endif // DEFINE_MACRO_H


ex)

VERBOSE(); // 현재 위치 로그 출력

DEBUG("Something is wrong here"); // 현재 위치에 문자열과 함께 로그 출력

SDEBUG("Something is wrong with value [%d]", wrongValue); // 현채 위치에 printf 포맷 형태로 로그 출력


보면 알겠지만 ENTIRE_DEBUG_ON 을 0으로 바꾸면 모든 디버그 메시지 출력을 끈다.

DEBUG_VERBOSE 를 0으로 바꾸면 VERBOSE만 끈다. 이건 응용해서 디버그 레벨을 조절하면 될듯.



Posted by 독뽀
,

SDK Ver. Qt 4.8.6


현상)

QByteArray 객체를 기본 생성자로 선언하고 reserve 로 크기를 정하고 복사를 하니 size가 제대로 나오지 않았다.

resize 로는 정상 동작 하였다.


const char *cba = "great!";

QByteArray ba;
ba.reserve(10);

memset(ba.data(), 0, 10);
mempcpy(ba.data(), (const char*)cba, 6);

qDebug() << "ba = " << ba.data();

qDebug("ba size[%d] ba isNull[%d]", ba.size(), ba.isNull());


원인)

size가 제대로 동작하지 않은 이유..

QByteArray 객체를 기본 생성자로 생성하면 QByteArray 내부 private 변수인 d (구조체 포인터) 값을 shared_null 의 주소 값으로 설정한다. 이후 reserve 를 호출하면 내부적으로 QByteArray의 realloc을 호출하게 되는데 여기서 문제가 발생한다.


realloc 내부를 보면 아래와 같이 x라는 변수에 메모리를 할당 받고 d가 x를 가리키게 한다.


void QByteArray::realloc(int alloc)
{
    if (d->ref != 1 || d->data != d->array) {
        Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc));
        Q_CHECK_PTR(x);
        x->size = qMin(alloc, d->size);
        ::memcpy(x->array, d->data, x->size);
        x->array[x->size] = '\0';
        x->ref = 1;
        x->alloc = alloc;
        x->data = x->array;
        if (!d->ref.deref())
            qFree(d);
        d = x;
    } else {
        Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc));
        Q_CHECK_PTR(x);
        x->alloc = alloc;
        x->data = x->array;
        d = x;
    }

}


d->size 값과 alloc 값 중 작은 값을 size로 넣게 되는데, 이 인자는 reserve 에서 인자로 넘어온 값이 realloc에서도 인자로 넘어가고 메모리를 할당 받게 된다.

하지만 d->size 값이 위의 코드로 인해 d->size 값 (0) 이 다시 기록되고 그 결과 size 함수를 호출하면 0이 나오는 기이한 현상이 발생한다.


이 예로 사용 된 QByteArray 객체는 size() 는 0이지만 data() 메서드로 호출해 보면 값이 들어 있다.



결론)

내가 아직 개념을 잘못 알고 있는 것이 아닐까 생각이 든다.

reserve 는 API 레퍼런스에 나와 있듯이 성능 튜닝 용도로만 사용하거나 사용 안하는 것이 좋겠다.


참고)

reserve는 할당된 크기보다 인자로 넘긴 크기가 클 경우에만 realloc 하는 인라인 함수로 구현. (5.x 에서는 좀 다름)

resize는 현재 크기보다 인자로 넘긴 크기가 클 경우 뿐 아니라 작은 경우에도 realloc을 한다.


'QT' 카테고리의 다른 글

undefined reference to 'vtable for...'  (0) 2016.05.19
반투명 그릴 때 배경 잔상 문제  (0) 2016.05.11
libwinpthread 가 계속 동적 빌드만 될 때  (0) 2016.04.28
디버깅 매크로  (0) 2016.04.19
QT static build with mingw32  (0) 2015.09.17
Posted by 독뽀
,

QT static build with mingw32

QT 2015. 9. 17. 13:52

웬만한건 이미지 파일에 묶어서 배포를 해서 따로 배포할 일이 없었지만..

별도 프로그램을 배포할 일이 생김 (상업용이 아니기 때문에 본인은 라이센스 문제에 해당되지 않았음)
따라서 번거로운 install 이나 별도 파일 배포를 막기 위해 정적 빌드를 알아봄

1. 동적 빌드는 qt 사이트에서 mingw32, sdk 및 qtcreator 로 작업해왔다면 별도의 설명은 하지 않겠음.
2. 정적 빌드
 - 1. 동적 빌드에서의 필수 구성 요소들이 설치되어 있다면 기존 버전과 같은 qt-everywhere... 소스 파일을 받아둔다.
 - 경로는 어디든 상관 없으나 본인 qt 설치 경로 아래에 static 이라고 두면 찾기 쉬움.
 - qt-everywhere.. 압축 파일을 C:\Qt\static 같은 곳에 푼다. 압축 파일의 이름으로 풀린 폴더 이름을 변경하였다.
 - 먼저 mingw32-make.exe 의 위치를 환경 변수에 등록 해준다. (본인은 C:\minGW32\bin 임)
 - cmd 창을 열고 static 폴더로 가서 README 와 INSTALL 파일을 읽어본다. 자세한 설명이 없다.
 - 바로 configure 를 해서 빌드하면 기존과 같은것이니 우리가 필요한 정적 precompile 환경을 만들도록 옵션을 주자.
   \> configure.exe -release -opensource -static -fast -no-qt3support -no-opengl -no-vcproj -no-phonon -no-audio-backend -no-declarative -nomake examples -nomake demos
 - 옵션은 configure.exe -help 를 치면 상세히 나온다. 나같은 경우 phonon 이 필요한데 저 옵션을 당연히 빼야겠지?
 - 예제가 필요하면 -nomake exmaples 를 빼면 된다. 본인이 찾는 qt 에서 제공하는 라이브러리는 help에서 나온 옵션에
 웬만하면 다 있다고 보면 된다. (무려 300라인이 넘어가서 여기 붙이진 않는다.)
 - configure 가 끝나면 mingw32-make sub-src 치면 빌드를 시작한다. (i7 - ssd - 16GB 인데도 한시간 넘게 걸림)
 - 본인은 에러가 안나서 어떤 삽질을 하지말라고 얘기를 못해주겠다. 문제가 있었으면 댓글 바람.
 - 이게 끝나고 나면 qtcreator 에서 어떤 Qt version 및 Tool chain 으로 할지 설정해서 빌드하면 끝이 난다.
 - 테스트는 release 모드로 놓고 빌드하고 생성된 실행 파일을 단독으로 실행해보면 된다.
  (qtcreator에서 run이 아니고 파일 경로로 가서 직접 실행)
 - 뭔가 오류가 나거나 이름을 모르겠다 싶으면 기존 qt project를 참조해보면 된다.
 - 가령 본인 mkspec 정확한 명칭을 모르겠다? qtcreator 에서 Tools > Options > Build & Run > Tool Chains 에서
본인이 사용 중인 Tool chain 을 선택해보면 제일 아래에 나온다. 
 
========================================================================
추가)
phonon 추가가 안됨.. static/src 쪽에 있는 3dparty 및 phonon 문제 추적 중..


========================================================================
추가)
http://doc.qt.io/qt-4.8/configure-options.html 에 가보면 -help 로 나오는 것보다 더 자세히 설명되어 있음.

-phononCompile the Phonon module.Phonon is built if a decent C++ compiler is used. This option denotes a default value and needs to be evaluated. If the evaluation succeeds, the feature is included.

evaluted.. 라이선스를 획득해야 하는 것으로 보임.

'QT' 카테고리의 다른 글

undefined reference to 'vtable for...'  (0) 2016.05.19
반투명 그릴 때 배경 잔상 문제  (0) 2016.05.11
libwinpthread 가 계속 동적 빌드만 될 때  (0) 2016.04.28
디버깅 매크로  (0) 2016.04.19
QByteArray 의 reserve() vs resize()  (0) 2016.03.18
Posted by 독뽀
,