삽질하는플머

KOL.PAS의 SHCreateMenuBar 호출부 수정

Lazarus/KOL-CE

윈도 CE는 종류도 참 많다. 델마당에 올렸던 글에 신성기님이 달아두신 답변을 옮겨본다.

신성기 (barmi)
Windows Mobile(WM)에 비해 Windows CE (WinCE)는 포괄적인 개념입니다. WM5는 WinCE5.0기반으로 구동되는 서브셋입니다. 즉, WinCE는 MS Platform builder로 만들어지는 Embedded OS의 총칭이고, Wimdows Mobile은 이전의 Palm sized PC -> Pocket PC의 차세대 명칭으로 WinCE 기반으로 쉘,기능의 guide line을 만들어 둔 것입니다.
WinCE와 WM의 버전을 비교해 보면 다음과 같습니다.
WinCE 2.1 - Palm Sized PC (Hand Held PC)
WinCE 3.0 - PocketPC 2000/2002/2003/2003SE
WinCE 4.2
WinCE 5.0 - Windows Mobile 5
WinCE 5.2 - Windows Mobile 6
WinCE 6.0 - Windows Mobile 7
실제 Pocket PC는 모두 WinCE 3.0기반으로 만들어 진 것이라, OS의 기본 성능은 동일하고 포함되는 shell이나 dll에 따라 버전이 구분됩니다.
참고하세요.


문제는, KOL로 빌드한 실행파일의 경우 친구놈의 아이나비 플러스에서 에러가 나는 현상이 발생한다는 것. KOL은 폼을 생성하면서 SIP부분을 구현하기 위해 SHCreateMenuBar 를 호출하는데, 아이나비 플러스의 aygshell.dll 에는 이 함수가 없기 때문이다. 또 다른 글에 휘오른님이 달아두신 댓글에서 보이듯 동일한 현상이 포켓피시 2003에서도 발생한다고 하는데,

휘오른 (leekg999)
저번에 라자루스로 wince용으로 만든 다음, 파일크기를 보니 기본이 1M 더군요. 그러려니 하고, 좀 지난 pda(h4150,ppc2003)에 올려서 실행했더니,겨우겨우 로딩한뒤에, 다운먹더군요.KOL-CE 는  실행순간 넉다운..;; 제가 라자루스를 컴퓨터 3대에 깔아서 해봤는데, 윈도우 환경을 너무 타는 것 같습니다. 어떤때는 컴파일 되고, 어떤때는 IDE에서 오류나고,크로스 컴파일을 지원한다는게 매력적인 환경이지만, 초보에겐 삽질이 힘들더라구요 ㅠ_ㅠ
(혹시 WM5 이상 기종에서 성능은 어느정도 나오는지 아시는 분 계시나요?)  


포켓PC 2003에 SIP 영역이 없다는 것을 고려하면 같은 이유라고 짐작된다. (시간 날 때, 책상위에서 잠자고 있는 poz에 밥을 먹인 뒤 테스트 해 봐야 겠다.)

아무튼 이 문제를 해결하려면 KOL.PAS의 TControl.CreateWindow 함수를 손 봐 주어야 한다. 버전 2.80.1 에서는 33,837 번 라인, 버전 2.80.2 에서는 33,845 번 라인을 아래와 같이 수정하자.

2009.1.28 추가.
2009년 1월 23일에 릴리즈 된 2.80.3 버전에서는 33,847 에 해당 코드가 있다. 이거 매번 귀찮으니... 패치를 만들어 보내야 할 듯...


 // if CePlatform <> cpSmartphone then begin
 // -->> 위 코드를 다음과 같이 수정한다. 
 if CePlatform = cpPocketPC then begin


CePlatform 이 단순히 cpPocketPC인 것으로 봐서... 아무래도 2003에서는 또 다른 삽질이 필요할 듯...
이 문서는 삽질이 끝난 뒤 다시 업데이트 하도록 하자.


-->> PocketPC 2003 에뮬레이터에서 굴려본 결과는, 위의 경우와 관계없이 제대로 동작한다. 
CePlatform 값 자체도 cpPocketPC로 인식되므로 사실 저 코드와 별 차이가 없어보인다...

쩝... 결국 POZ를 충전해야 한다는 건가...


델마당의 휘오른님의 댓글에 의하면, 저 코드를 적용했을 때 h4150, PPC2003 에서 정상동작 한다고 한다. 따라서 POZ 밥먹이기는 귀차니즘에 의해 잠정중단~~ ^^;

라자루스의 Unit output directory

Lazarus

라자루스의 컴파일러 옵션 중 Unit output directory 의 경우 초기값이 비어있지만, 만약 이 값의 기본값이 "$TargetCPU()-$TargetOS()" 로 설정될 수 있다면 지금처럼 여러 운영체제를 테스트할 때 아주 편할 것이다.

compileroptionsdlg.pp 로 부터 추적을 시작해 보니, 라자루스의 프로젝트는 c:\lazarus\ide\project.pp 에 정의된 TProject형 객체인 Project1에 대부분의 옵션들이 저장되어있는 것으로 보인다.
이 놈의 TProjectCompilerOptions 형 멤버인 FCompilerOptions 에  UnitOutputDirectory 라는 프로퍼티가 있군.
따라서 Project1 이 생성될 때 이 값을 조절해주면 될 것 같다.

이 객체는 c:\lazarus\ide\main.pp 의 8248 라인에서 다음 코드로 생성된다.

Project1:=CreateProjectObject(ProjectDesc,ProjectDescriptorProgram);
try
  Project1.BeginUpdate(true);
  try
  ....


따라서 여기에서 내가 원하는 값을 지정 해 보자. 

Project1.CompilerOptions.UnitOutputDirectory:= '$TargetCPU()-$TargetOS()';


라자루스를 재빌드하고 다시 실행 시킨 후 새 프로젝트를 선택하고 Project -> Compiler Options 를 보자.


이야~~ 제대로 된다~~

재빌드한 RTL, FCL 유니트들을 적용하기 위한 스크립트

Lazarus
재빌드한 rtl, package 유니트들을 라자루스에 적용하기 위한 스크립트이다.
cygwin 상에서 실행시키면 컴파일된 유니트들을 제 위치에 옮겨준다.

역시 셸 스크립트는 어렵다... (보고 웃지 마세요!)

moveunits.sh


#!/bin/sh 
#

# 라자루스의 유니트들을 정돈하기 위한 스크립트. 
# 인자값으로는 소스디렉토리, 유니트디렉토리, 그리고 작업할 유니트 타입을 받는다. 
#
# rtl의 경우 다음과 같다. 
#
# 1. /cygdrive/c/lazarus/fpc/2.2.2/source/
# 2. /cygdrive/c/lazarus/fpc/2.2.2/units/
# 3. i386-win32 
# 
# fcl의 경우 다음과 같다. 
#
# 1. /cygdrive/c/lazarus/fpc/2.2.2/source/packages/
# 2. /cygdrive/c/lazarus/fpc/2.2.2/units/
# 3. i386-win32 

# 시작위치를 저장 해 둔다. 
StartPath="$(pwd)";

if [ $# -eq 3 ]; then
  echo "실행인자를 받았습니다."
  echo "소스 디렉토리  : "$1
  echo "유니트 디렉토리: "$2
  echo "유니트 타입    : "$3
  
  # 소스 디렉토리로 이동. 디렉토리를 추출. 
  cd $1;
  SubDirs=($(ls -ltr $1 | grep -v total | awk '{print $NF}'));
  echo "서브디렉토리 갯수 : "${#SubDirs[*]};
  
  for Dir in ${SubDirs[*]} 
  do
    # 주어진 디렉토리 밑에 /units/$3 이 존재하는지 살핀다. 
    if [ -a $1$Dir"/units/"$3 ]; then
      echo $1$Dir"/units/"$3
      echo " - 이동 대상입니다. "$2$3"/"$Dir"  옮깁니다." 
      # 옮겨갈 유니트 디렉토리 하부의 대상을 먼저 날린다. 
      rm  $2$3"/"$Dir -rf
      # 없는 경우를 대비해 생성도 해 둔다. 
      mkdir  $2$3
      # 디렉토리를 옮겨준다.
      mv $1$Dir"/units/"$3 $2$3"/"$Dir       # 원본의 컴파일된 유니트는 날려준다.       rm $1$Dir"/units/" -rf     fi   done; else   echo "실행인자의 갯수를 확인하세요." fi # 시작 위치로 되돌아간다. cd $StartPath;


i386-wince 용 크로스 컴파일 환경 만들기

Lazarus/Mobile
앞에서 설치한 Microsoft Windows CE 5.0 Emulator 를 위한 i386-wince 크로스 컴파일 환경을 구축 해 보자. 

먼저 리테일 버전의 컴파일러 소스를 다운받아 압축을 푼다. 

  fpcbuild-2.2.2.zip

압축을 풀어 생성된 fpcsrc 를 d:\programs\fpc 에 옮겨두자.

GNU utils package 가 필요하다. 여기에서 다운받아 D:\Programs\coreutils 에 풀어둔다. Dependencies 도 함께 다운 받아 풀어둔다.

이미 라자루스/FPC가 설치된 상태이므로 커맨드 창을 하나 띄운 뒤 다음과 같이 입력한다.

cd D:\Programs\fpc\compiler
PATH=c:\lazarus\fpc\2.2.2\bin\i386-win32;D:\Programs\coreutils\bin
make cycle CPU_TARGET=i386 OS_TARGET=wince

결과로 얻어진 ppcross386.exe 을 c:\lazarus\fpc\2.2.2\bin\i386-win32 로 옮긴다.

참고. strip ppcross386.exe 해 주면 용량이 조금 줄어든다...


이제 라자루스 fpc로 가서 rtl을 컴파일하자.

PATH=c:\lazarus\fpc\2.2.2\bin\i386-win32
cd C:\lazarus\fpc\2.2.2\source\rtl
make CPU_TARGET=i386 OS_TARGET=wince PP=ppcross386.exe

C:\lazarus\fpc\2.2.2\source\rtl\units\i386-wince 를 C:\lazarus\fpc\2.2.2\units\i386-wince\rtl 로 복사한다.

다음은 패키지 빌드.

cd C:\lazarus\fpc\2.2.2\source\packages
make CPU_TARGET=i386 OS_TARGET=wince PP=ppcross386.exe

완료된 패키지들의 unit 폴더를 하나씩 C:\lazarus\fpc\2.2.2\units\i386-wince\ 밑으로 옮겨준다. 예를 들어 C:\lazarus\fpc\2.2.2\source\packages\chm 패키지는 위의 작업을 끝내면 units 밑에 i386-wince 폴더가 생성되는데 이 폴더를 잘라다가 C:\lazarus\fpc\2.2.2\units\i386-wince\chm 이라는 이름으로 옮겨주어야 한다는 이야기. 이거 되게 귀찮은데... 다음번에도 이 작업을 해야 한다면, 적당한 셸 스크립트나 유틸리티를 만들어야 겠다. 참고로 i386-wince 용으로 빌드되어 옮겨주어야 하는 패키지는 다음과 같다.

chm
fcl-base
fcl-db
fcl-fpcunit
fcl-image
fcl-json
fcl-net
fcl-passrc
fcl-process
fcl-registry
fcl-web
fcl-xml
fftw
fpmkunit
hash
ibase
libgd
mysql
numlib
odbc
oggvorbis
openssl
oracle
pasjpeg
paszlib
postgres
regexpr
sdl
sqlite
symbolic
tcl
unzip
winceunits
zlib

FCL을 디버깅 정보 포함하여 빌드하는 방법에 대한 포럼글이 읽었는데, 글 말미에 /usr/lib/fpc/2.2.0/units/ 에서 각 유니트에 대한 심볼릭 링크를 걸어주었다는 멋진 아이디어가 있었다. 윈도에서는 Junction 이 해법이 될 듯 한데... (강좌는 여기)... 시간 날 때 이 방법도 추가로 정리 해 보자.

일단 끄적 끄적 셸 스크립트를 만들어 두었다. 뭐 잘 동작하는군.
http://oranke.tistory.com/entry/MoveUnits

컴파일 옵션 -FU 를 사용하면 대상 폴더를 지정할 수 있다. 이걸 쓰면 귀찮은 스크립팅도 필요없어질 듯...

-FU<x>     Set unit output path to <x>, overrides -FE

OPT="-FUC:\Test" 이런식으로...

마지막으로 LCL을 빌드한다.

그 전에 해야 할 일이 하나 있는데, 사실 컴파일러는 실행파일을 만드는 여러 종류의 툴들 중 일부분일 뿐이다. 이 외에도 어셈블러, 링커 등 많은 도구들이 필요하며 이들을 일컬어 binutils 라고 부른다. 그런데 현재 대상 CPU가 i386이므로 binutils 는 라자루스 설치시 제공된 i386-win32 용을 그대로 사용할 수 있다. (사실 컴파일러도...^^) 현 시점에서 리소스 컴파일러인 windress.exe 만 Target-OS 용을 요구된다. 따라서 c:\lazarus\fpc\2.2.2\bin\i386-win32 에 있는 windres.exe 를 i386-wince-windres.exe 로 복사하면 아무 문제없이 LCL을 컴파일 할 수 있다.
(나중에 링커(ld.exe) 나 어셈블러(ar.exe)가 요구된다면 동일한 방법으로 복사 후 이름변경하여 사용하면 된다.)

cd C:\lazarus\lcl
make CPU_TARGET=i386 OS_TARGET=wince PP=ppcross386.exe


이제 컴파일러 옵션에서 Target CPU Family 를 i386 으로 설정하고 리빌드 한다. 




프로젝트 밑에 i386-wince 폴더에 생성된 실행파일을 Microsoft Windows CE 5.0 Emulator 로 옮겨 실행시켜보자. 잘 실행된다. 


 

일단은 여기까지. 라자루스가 만들어내는 후덜덜한 실행파일의 크기와 KOL-CE에 대해서는 여기에 주절거려 두었다.


라자루스 시작하기

Lazarus
윈도 재설치 기념으로 라자루스 설치 및 설정과정을 정리 해 보자.
대상은 Lazarus 0.9.26. FreePascal 2.2.2. 

다음 두 개의 배포판을 설치한다.





코딩 화면은 오래도록 사용해 눈에 익은 설정으로 수정 해 주었다. (Environment -> Editor Options)




여기 참고하여 디바이스 에뮬레이터를 설치 해 주자. 

 1. Microsoft Device Emulator
    V1Emulator.zip 와 efp.msi 다운로드. 먼저 V1Emulator.zip 만 설치.

  2. Microsoft Virutal PC 2007 - Machine Network Driver를 위해 설치함.

  3. 1에서 다운받아 둔 efp.msi (윈도 모바일 5.0 이미지) 를 설치한다.




심심할 때 네비같은 WinCE 코어용으로 만들어 돌려 볼 윈도 CE 5.0 에뮬레이터도 설치 하자.

  Microsoft® Windows® CE 5.0 Device Emulator - setup.exe 다운받아 설치.


 

CE 5.0 에뮬레이터를 세로로 돌리는 방법은 코드기어의 닷넷관련 링크를 참고하여 세로로 돌리는 단축아이콘을 만들어 주었다. (디바이스의 공유폴더는 라자루스 작업폴더의 #Share가 되도록 하였다.)

"C:\Program Files\Windows CE 5.0 Emulator\Emulator_500.exe" nk.cem /vmid {6F5AE65B-98FF-46A9-A0E1-29B82C9779D4} /vmname "CE 5.0" /sharedfolder "D:\My Works\Lazarus\#Share" /video 240x320x16


 



이 에뮬레이터에서 CPU정보를 살펴보면 인텔계열로 표시된다. 때문에 앞에서 설치한 arm-wince용 크로스 컴파일 환경으로는 여기서 동작하는 바이너리를 만들지 못한다. 따라서 i386-wince 툴체인을 구성 해 주어야 하는데... 이 내용은 다음번 글에서 살펴보도록 하자.



2009.1.22.

그 외 비주얼 C++ 2005 이상을 설치하지 않고 동작시켜 볼 수 있는 에뮬레이터 정보를 나열 해 본다.

* 일단 무료 개발툴인 Embedded VC++ 4.0 그리고 서비스팩 4.
  개발에 필요한 참조자료를 살펴볼 때 좋다. 게다가 쓸만한 리소스 편집기 까지... 무조건 깔자.
* 여기에 추가로 CE 5.0 용 Standard SDK, 그리고 Pocket PC 2003 SDK.
  이 둘을 설치하면 위에서 살펴본 CE 5.0 에뮬레이터와 Pocket PC 2003 에뮬레이터가 설치된다.
  다만 XP에서는 PPC2003 에뮬레이터가 구동되지 않는데, 이 부분에 대해서는 여기에 설명 해 두었다.
* PPC 2003 에뮬레이터도 따로 링크가 있는데... 깔아야 하는지 아닌지 기억이 가물가물~~
* 윈도 모바일 6 SDK는 비주얼 C++ 2005 이상을 요구하므로 가볍게 패스~~
* 윈도 모바일 6.1.4 에뮬레이터 이미지. 모바일 6 SDK 없이도 단독으로 구동된다. 
  옴니아, 또는 터치다이아몬드 같은 800*480 환경도 구경 해 볼 수 있다.
* 윈도 모바일 6 로컬라이즈 이미지를 설치하면 한글 환경도 테스트 해 볼 수 있다.

2009.2.4.
* VS 2008에 함께 포함된 디바이스 에뮬레이터 V3도 단독배포되고 있었다.



설치가 마무리 되었으니 테스트를 해 볼 차례이다. 

새로운 프로젝트를 만들고 "D:\My Works\Lazarus\200901\Test001" 에 저장한다.
Project -> Compiler Options 에서 Unit Output directory에 다음과 같이 입력하여

$TargetCPU()-$TargetOS()\




프로젝트를 만들 때 마다 이 값을 저장하는 것도 일이라... "Set as default"같은 것이 있으면 좋을텐데...
고민하다가 라자루스의 소스를 수정하여 아예 기본값으로 만들어버렸다. 자세한 이야기는 여기를 참조.


컴파일된 결과물이 각 CPU/OS별로 분리되도록 하자.




11메가나 되는 실행파일 이야기는 차차 하도록 하고, 일단 버튼을 하나 올려두고 이벤트 핸들러에서 Close()를 호출하여 어플리케이션을 종료하도록 해 보자. 실행 해 보면 잘 동작한다.




이번에는 윈도 모바일용 바이너리를 만들어 보자. 컴파일러 옵션을 열어 Paths 페이지의 LCL Widget type 을 Wince (beta) 로 바꾸어 준다.




이번에는 Code 페이지로 가서 Target OS 는 WinCE, Target CPU famuly 는 arm 으로 변경한다.




다시 빌드 해 보면 프로젝트 폴더 밑에 arm-wince 라는 폴더가 생겨날 것이다. 위에서 설치했던 포켓피시 에뮬레이터로 가져와 실행시켜보면 잘 동작하는 것을 확인할 수 있다.






라자루스를 설치하고 윈32 및 윈도 모바일용 실행파일을 만드는 법을 알아보았다.
다음 글에서는 윈도CE 5.0 에뮬레이터를 위한 i386-wince 크로스컴파일 환경을 만드는 방법을 살펴보도록 하자.