ICU 라이브러리 MSVC로 빌드

매우 오랜만에 ICU를 빌드하려하다보니 Windows SDK Version이 변경되지않는 이상한 문제가 발생하였다. 이거로 두시간동안 구글링도해보고 솔루션, 프로젝트, 프로퍼티 파일을 열어보아도 답이 안나와서 결국 MSYS2에서 빌드하였다(…).

빌드방법은 간단. VC 콘솔에서 MSYS2가 설치된 폴더로 이동 후 msys2_shell.cmd -use-full-path 명령으로 실행하면 프롬포트의 환경번수가 유지되어 bash 쉘이 뜨게된다. 이제 압축을 푼 icu 폴더의 source 폴더로 이동하여 ./runConfigureICU MSYS/MSVC --prefix=/d/OpenSource/icu-67.1.x64 --enable-tests=no --enable-samples=no 이런식으로 Makefile을 생성. 그리고 원인은 모르지만 config 파일을 정확하게 지정하지 못하는데… 이건 source 폴더의 하위 폴더인 config에서 cp mh-msys-msvc mh-unknown와같이 복사 후 make하면 끝. (nmake가 아닌 make 명령. 만약 D 옵션을 알 수 없다는 오류가 뜬다면 /usr/bin/link.exe 파일의 이름을 잠깐 다른 이름으로 바꾸면 오류를 회피할 수 있다. tests를 비활성화하면 링크에서 오류가 난다.)

이것으로 삽질 끝.

만약 위와같이 rc 명령에서 오류가 난다면 data 폴더에 out폴더 생성, 그 안애 tmp 폴더를 생성하면 된다. 추가로 extra의 scptrun에서 링크오류가 발생하면 해당 폴더의 makefile을 열어서 LINK.cc를 검색하여 -o $@ 부분을 -out:$@로 변경하면 된다.

CMake-gui를 Qt5환경으로 빌드하기

빌드하게 매우 귀찮아 CMake를 MSI 패키지로 설치를 하다가 매우 오랜만에 직접 빌드해보았다. (대신 MSYS2를 깔아야한다.) 전에는 Qt4를 사용했기때문에 쉽게 빌드된거같은데 Qt5를 사용한 GUI 환경을 빌드하려하니 구글링도 안되어 꽤나 삽질했다. CMakeLists.txt를 열어보면 Qt5를 지원하는 모양이였지만 find_package(Qt5Widgets QUIET)구문이 어떻게 동작하는지 알 수 없어 리눅스 환경에서 bootstrap을 실행하여 생성된 CMakeCache.txt 파일을 직접 분석하여 찾아본 결과 -DBUILD_QtDialog=ON -DQT_QMAKE_EXECUTABLE=D:\OpenSource\Qt5.15.0.x64\bin\qmake.exe -DQt5Widgets_DIR=D:\OpenSource\Qt5.15.0.x64\lib\cmake\Qt5Widgets 이렇게 변수를 설정하면 된다는것을 알게되었다.

자세한 내용은 CMake 소스코드에서 README.rst 파일을 열어보면 되고 이미 빌드된 CMake가 없는 상태에서 간략한 빌드과정은

MSYS2를 설치한다. 설치완료 후 MSYS2를 실행하고 pacman -S --needed git base-devel mingw-w64-x86_64-gcc 명령으로 필요한 패키지를 설치한다. (git는 필요없어보이지만 README.rst에서 설치하라고하니..) 그 후 exit 명령으로 쉘을 종료하고 시작메뉴에서 MSYS2 MinGW 64bit를 실행한다. 이렇게 기본 빌드환경은 끝.

3.18.1버전의 cmake를 압축 풀었다면 폴더 이름이 cmake-3.18.1일것이다. 압축 푼 경로가 D:\OpenSource\cmake-3.18.1 이라면 cd /d/OpenSource 명령으로 폴더 이동 후 임의 폴더 생성한다. (cmake-build1로 만들었다.) cmake-build1 폴더에서 ../cmake-3.18.1/configure –prefix=/d/OpenSource/cmake-bootstrap 명령을 실행 후 make && make install 명령을 실행하여 빌드 및 바이너리를 설치한다. 이렇게 bootstrap 환경은 완료.

Visual Studio의 64비트 툴 콘솔을 실행하여 set PATH=%PATH%;C:\msys64\mingw64\bin 명령을 수행 후(msys2를 기본 경로에 설치했을경우) D:\OpenSource\cmake-build2 폴더를 생성 & 이동하여 ../cmake-bootstrap/bin/cmake ..\cmake-3.18.1 -DCMAKE_INSTALL_PREFIX=D:\OpenSource\cmake -DBUILD_QtDialog=ON -DQT_QMAKE_EXECUTABLE=D:\OpenSource\Qt5.15.0.x64\bin\qmake.exe -DQt5Widgets_DIR=D:\OpenSource\Qt5.15.0.x64\lib\cmake\Qt5Widgets 이렇게 실행하면 Visual Studio Solution 파일(CMake.sln)이 생성된다. (nmake 타겟으로 생성가능하지만 VS 솔루션 파일에서 빌드하면 병렬빌드가 되기에 그냥 기본 타겟으로 생성하였다.) 이제 솔루션 파일을 열고 빌드 형식을 Release / x64로 설정하여 CMakePredefinedTargets/ALL_BUILD 프로젝트를 우클릭하여 빌드 메뉴를 선택한다. 모두 빌드되면 CMakePredefinedTargets/INSTALL 프로젝트를 우클릭하여 빌드 메뉴를 선택하면 CMAKE_INSTALL_PREFIX로 설정된 D:\OpenSource\cmake에 CMake가 설치된다.

D:\OpenSource\cmake\bin\cmake-gui.exe 파일을 실행하면 DLL 종속성 오류가 뜰것이다. 명령 프롬포트에서 D:\OpenSource\cmake\bin 폴더로 이동 후 D:\OpenSource\Qt5.15.0.x64\bin\windeployqt.exe cmake-gui.exe 명령을 실행하면 종속된 파일이 전부 복사되고 이제 cmake-gui.exe를 실행하면 아래와같이 GUI 환경의 cmake 프로그램이 실행된다.

이제 필요한것들을 빌드해야겠다. 실행도 깔끔하게 잘 되니 이것으로 끝!

eclipse에서 spring, maven 사용시 ClassNotFoundException 및 LOC Header 등 에러 발생시 확인해볼 사항

오랜만에 스프링 사용해볼겸 boot를 써보았다.

이전엔 maven – update project를 해보면 Invalid LOC Header (bad signature) 문제가 발생하였다며 파일이름이 나타났기때문에 바로 찾아서 지운 후 update project를 하면 되었는데…
이번엔 war이나 jar파일로 패키징까지 다 되었지만 함께 패키징 된 jar 파일이 문제있어 예외가 발생하였다.
디버그 모드로 실행하면 예외가 발생하고 해당 예외의 객체 이름부분을 콘솔 출력에서 클릭하면 Break Point를 활성화 할 수 있어 ZipException을 등록해두었더니 아래와같이 스택에서 파일명을 확인할 수 있었다.

그리고 콘솔에서 해당 경로를 보면 항상 보이는 파일이 있다.

바로 sha1-in-progress 확장자를 가진 파일이다. jar파일을 지운 후 update project를하여 jar 파일이 다 받아지면 sha1-in-progress파일이 사라진다.

이런점을 활용하면 탐색기를 띄운 후 경로표시줄에 %userprofile%\.m2 를 넣은 다음 검색에 sha1-in-progress를 입력하면 아래와같이 죽죽 뜬다. (많이도 실패했네 -_-)

콘솔이 편하면 콘솔에서, 탐색기가 편하면 탐색기에서 해당 경로에서 jar 파일을 지운 후 update project를 한번 해주자.

jar 파일을 지우고 update project를 해서 jar 파일이 완전하게 받아져도 sha1-in-progress파일이 남는경우가있다. (아마 남는경우가 더 많은거같다.) 그냥 폴더를 지우는것도 깔끔한 방법이다.

P.S.
하… 전혀 힌트도 얻지 못할 콘솔 메시지… 다운로드가 도중에 끊기는건 대체 어느시대에 일어나는 일이란 말인가… 덕분에 하루 반나절을 구글링으로 -_-;;;
수년도 더 지난 이런 문제 이제 좀 알아서 sha1 해쉬를해서 안맞는 파일은 다운받는 메뉴 좀 넣어주지. -_-;;

오늘의 네시간짜리 QtMultmedia QAudioInput 뻘짓.

format은 아래와같이

QAudioFormat formatAudio;
formatAudio.setSampleRate(44100);
formatAudio.setChannelCount(2);
formatAudio.setSampleSize(24);
formatAudio.setCodec("audio/pcm");
formatAudio.setByteOrder(QAudioFormat::LittleEndian);
formatAudio.setSampleType(QAudioFormat::SignedInt);

audio device info는 아래와같이

QAudioDeviceInfo getAudioDevice(const QString &name)
{
  foreach(const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioInput))
  {
    if(deviceInfo.deviceName() == name)
    {
      return deviceInfo;
    }
  }
  return QAudioDeviceInfo();
}

audioDevice = getAudioDevice(“hw:CARD=G5,DEV=0”);

그 후 start하면 iodevice에 어떠한 데이터가 수신되지 않는다. 결론은 이유가 Qt는 24비트 셈플은 S24_LE로 초기화 하기때문이였다.

쉘에서 아래처럼 정보를 확인해보면 지원하는 포맷은 S24_3LE(…)

$ cat /proc/asound/card2/stream0
Creative Technology Ltd Sound BlasterX G5 at usb-3f980000.usb-1.3.1, high speed : USB Audio

Playback:
  Status: Stop
  Interface 1
    Altset 1
    Format: S24_3LE
    Channels: 2
    Endpoint: 1 OUT (ASYNC)
    Rates: 44100, 48000, 88200, 96000
    Data packet interval: 500 us

Capture:
  Status: Stop
  Interface 2
    Altset 1
    Format: S24_3LE
    Channels: 2
    Endpoint: 2 IN (ASYNC)
    Rates: 44100, 48000, 88200, 96000
    Data packet interval: 500 us

좀 더 깔끔하게 코딩하기위해 Qt의 Multmedia를 사용하려했지만 결국 alsa api를 써야할거같다. 아… 왜 저런 차이를 생각하지 못하고 네시간을 삽질했을까… PulseAudio를 활성화 시키면 리셈플링 되어 처리가 가능할거같은데 lite 이미지에서 PulseAudio를 활성화 하는 방법이 구글링되지않아 그건 포기해야겠다.

Qt 5.8.0 WebEngine 모듈 빌드

보통은 그냥 Qt 홈페이지에서 빌드된것을 받아서 설치해도된다. 단, 5.8.0은 배포중인 VS 2017 타겟 바이너리가 없고, 디버깅 시 상황에 따라서는 약간 더 유리하기때문에 직접 빌드하는걸 선호한다. (그리고 그냥 갠적인 취향 약 80%) 이전에 누수를 찾을 수 없어 직접 빌드하여 QtSql의 ODBC 플러그인 메모리 누수 버그를 찾아내고 코드 리뷰에 올리고 커밋하여 아마도 5.6.0버전부터 적용되어있다는건 안비밀(…)

일단 두서없는 글이였지만 이것을 참조하여 OS의 비 유니코드 환경을 영어(미국)으로 바꾸는것이 이롭다.

이번에도 직접 빌드 삽질. 5.7.0과는 다르게 필요한 것들은 다 있는데 configure 후 nmake(or jom)을 해도 웹 엔진이 빌드되지않았다. 영문 문서…에서는 일단 해석도 잘 못하고 그냥 봤을때는 별다른 언급이 없었다. 정말 아무리 찾아봐도 별다른 내용이 없었다. (덕분에 5~6번은 distclean & build 한거같다.)

문서에 Qt 개별 모듈을 받아서 빌드 언급이 잠깐있어서 혹시나하여 소스코드에서 qtwebengine 폴더로 이동 후 qmake & nmake(or jom)을 실행하니 빌드가되었다. 아마도 이게 워낙 오래걸리고 덩치가 커서 기본적으로 skip 처리되어있는거 아닌가 싶다. 하지만 규모가 큰 C++ 프로젝트는 오류 한두개 생기는 법. 그래서 직접 빌드를 해본 내용을 정리.


환경 1
Visual Studio Community 2015 Update 3 (최소 Update 2가 요구된다.)
Windows SDK 10.0.15063.137

환경 2
Visual Studio Community 2017
Windows SDK 10.0.1563.137 (Visual Studio 2017에서 함께 설치되는 Windows SDK 10은 지우고 ISO 파일을 받아서 다시 깔았다. 필요에 의해서였는데 왜인지 기억이 안난다 -_-)


공통
Perl 최신버전 (Qt 문서에서는 Active Perl로 명시되어있지만 Strawberry Perl로도 가능)
Python 2.7.5 or later (Qt 문서에서는 2.7.5 or later로 명시되어있지만 3버전으로 테스트 안해봤음)
메모리는 8기가 이상.. 왠만하면 16기가 이상을 권장한다. 이것역시 WebEngine에서 사용하는 Chromium의 코그가 워낙 방대해서 메모리에 파일캐쉬를 많이 못하면 디스크 IO가 많이발생하여 빌드 속도에도 영향이있다.


Windows SDK 10을 설치하면 mt.exe 파일을 못찾는 경우가 발생한다. 명령줄에서 mt를 쳐서 명령을 못찾는다면 아래처럼 환경변수에 추가해야한다.
32비트 도구 프롬포트 환경
set PATH=%PATH%;C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x86
64비트 도구 프롬포트 환경
set PATH=%PATH%;C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x64


환경 1에서의 WebEngine 에러 수정
코드 리뷰: https://codereview.chromium.org/2317773002/patch/60001/70005

소스코드 폴더 기준으로 “qtwebengine\src\3rdparty\chromium\device\bluetooth” 경로의 bluetooth_task_manager_win.cc 파일을 열고 OnGetGattEventWin 함수가 정의된 157줄을 void 뒤 CALLBACK 추가하여 void CALLBACK OnGetGattEventWin으로 정의를 변경

환경 2에서의 configure 에러 수정
코드 리뷰: https://codereview.qt-project.org/#/c/177743
이건… 수정할게 좀 많다. 그냥 이 페이지를 참고해서 비교하어 수정하는게 나을것같다. qalgorithms.h파일의 경로는 “qtbase\src\corelib\tools”이다.
만약 직접 수정하기가 좀 그렇고 5.8.0버전의 코드를 빌드한다면 이 주소로 파일을 받은다음 압축을 풀고 이름을 원래대로 수정한다음 덮어씌워도 된다.


아래는 내가 사용한 configure 명령 줄
configure -opensource -confirm-license -prefix D:\OpenSource\Qt5.8.0 -opengl dynamic
opengl 옵션을 지정안하면 es2로 설정되고 5.5부터는 dynamic을 기본으로 사용하는 것 같다. (참고)
prefix는 빌드 후 nmake install 하면 바이너리와 헤더가 설치되는 경로.


configure 명령이 완료된 후 nmake(or jom)을하면 문제없이 빌드 될것이며 이후 nmake install(or jom install)을하면 기본 Qt 모듈들이 복사될것이고, WebEngine을 빌드하려면 소스코드 폴더에서 qtwebengine 폴더로 이동한 후 qmake하고 역시나 nmake(or jom)하여 빌드, nmake install(or jom install)하면된다.

단지 주의할것으로는 perl, python명령이 실행되는지, flex, bison, gperf명령이 실행되는지 확인하는것이 좋다. Qt 소스코드 내 gnu 명령어들이 있으니 아래처럼 환경변수를 변경하여 재공되는거로 쓰는게 이로울거같다. (소스가 “D:\OpenSource\qt-everywhere-opensource-src-5.8.0″에 있다는 가정)

set PATH=%PATH%;D:\OpenSource\qt-everywhere-opensource-src-5.8.0\gnuwin32\bin;D:\OpenSource\qt-everywhere-opensource-src-5.8.0\qtbase\bin

환경변수가 잘 설정되었다면 아래와같이 각각의 버전정보를 볼 수 있다.

D:\OpenSource\qt-everywhere-opensource-src-5.8.0>python --version
Python 2.7.13

D:\OpenSource\qt-everywhere-opensource-src-5.8.0>perl --version

This is perl 5, version 24, subversion 1 (v5.24.1) built for MSWin32-x64-multi-thread

Copyright 1987-2017, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.


D:\OpenSource\qt-everywhere-opensource-src-5.8.0>bison --version
bison (GNU Bison) 3.0
Written by Robert Corbett and Richard Stallman.

Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

D:\OpenSource\qt-everywhere-opensource-src-5.8.0>flex --version
flex 2.5.37

D:\OpenSource\qt-everywhere-opensource-src-5.8.0>gperf --version
GNU gperf 3.0.1
Copyright (C) 1989-1998, 2000-2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Douglas C. Schmidt and Bruno Haible.

뭐… 갠적으로는 webengine을 사용할 일이 없지만 왠지 5.7 빌드할때와 달라서 불필요한 삽질을 한거같다(…)