From Evernote: |
全Linux生活:第16天 - 在Linux下編譯Windows DLLs |
最近工作上要做一個Windows下的JNI DLL,這原本在純Windows下是很簡單的事,但在Linux下,是有那麼一點麻煩。在Linux下要做cross platform compile,有幾個選擇:MingGW,Cygwin。但如果考量到team work的話,要強迫其他人也要使用Linux來寫程式也說不過去,所以目前暫時不考慮"純種"的cross platform compilation,我的作法是使用Windows下的C/C++ Compiler來進行編譯,考量到Comiler大小與不要有runtime相依性問題,那選擇有3個Visual C++ 6.0,MinGW Windows版,Borland C++ 5.5(什麼﹍這鬼東西還有人用嗎?)。當然,可以免費使用的只有MinGW與Borland C++ 5.5,而且Size最小的是Borland C++ 5.5,只需要50MB左右,最大的是Visual C++ 6.0,約180MB,第二名是MinGW,約120MB。
可是這些東西在Linux下可以用嗎?當然是不能直接用,但是透過WINE就可以。這樣做最大的好處是同一個專案可以在Linux與Windows下通用(甚至Mac OS X,但一樣要裝WINE才行)。
不囉唆,先準備JNI環境:
如果想用Visual C++ 6.0,請服用:
- 取得VIsual C++ 6.0:噓﹍不要問很恐怖﹍
- 安裝Visual C++ 6.0:
$ wine <PATH-TO-MSVC60-CD>/setup.exe - 在Eclipse建立MSVC60專案(General Project就可以了)
- 複製Compiler檔案:
$ cp -rvf "~/.wine/drive_c/Program Files/Microsoft Visual Studio/Common" <PATH-TO-MSVC60-PROJECT>
$ cp -rvf "~/.wine/drive_c/Program Files/Microsoft Visual Studio/VC98" <PATH-TO-MSVC60-PROJECT> - 複製並修改vcvars32.bat:
$ cp <PATH-TO-MSVC60-PROJECT>/VC98/Bin/VCVARS32.BAT <PATH-TO-HELLOWORLDJNI-PROJECT>/src/jni/bin/vcvars32.bat
$ vi <PATH-TO-HELLOWORLDJNI-PROJECT>/src/jni/bin/vcvars32.bat
@echo off
set MSVC60_HOME=%CD%\..\..\..\msvc60
rem
rem Root of Visual Developer Studio Common files.
set VSCommonDir=%MSVC60_HOME%\Common
rem
rem Root of Visual Developer Studio installed files.
rem
set MSDevDir=%MSVC60_HOME%\Common\msdev98
rem
rem Root of Visual C++ installed files.
rem
set MSVCDir=%MSVC60_HOME%\VC98
rem
rem VcOsDir is used to help create either a Windows 95 or Windows NT specific path.
rem
set VcOsDir=WIN95
if "%OS%" == "Windows_NT" set VcOsDir=WINNT
rem
echo Setting environment for using Microsoft Visual C++ tools.
rem
if "%OS%" == "Windows_NT" set PATH=%MSDevDir%\BIN;%MSVCDir%\BIN;%VSCommonDir%\TOOLS\%VcOsDir%;%VSCommonDir%\TOOLS;%PATH%
if "%OS%" == "" set PATH="%MSDevDir%\BIN";"%MSVCDir%\BIN";"%VSCommonDir%\TOOLS\%VcOsDir%";"%VSCommonDir%\TOOLS";"%windir%\SYSTEM";"%PATH%"
set INCLUDE=%MSVCDir%\ATL\INCLUDE;%MSVCDir%\INCLUDE;%MSVCDir%\MFC\INCLUDE;%INCLUDE%
set LIB=%MSVCDir%\LIB;%MSVCDir%\MFC\LIB;%LIB%
set VcOsDir=
set VSCommonDir= - 建立cl.bat:
$ vi <PATH-TO-HELLOWORLDJNI-PROJECT>/src/jni/bin/cl.bat
echo off
@call bin\vcvars32.bat
cl %* - 編輯build.xml:
$ vi <PATH-TO-HELLOWORLDJNI-PROJECT>/build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="Packaging Generator" default="all">
<property name="dir.src" value="src" />
<property name="dir.src.java" value="${dir.src}/java" />
<property name="dir.src.junit" value="${dir.src}/junit" />
<property name="dir.src.jni" value="${dir.src}/jni" />
<property name="dir.src.jdkinclude" value="${dir.src}/jni/jdk_include" />
<property name="dir.etc" value="etc" />
<property name="dir.lib" value="lib" />
<property name="dir.deploy" value="deploy" />
<property name="dir.classes" value="tmp" />
<property name="dir.build" value="build" />
<target name="all">
<antcall target="HelloWorld.dll" />
</target>
<target name="HelloWorld.dll">
<property name="moduleName" value="HelloWorld" />
<mkdir dir="${dir.deploy}" />
<delete>
<fileset dir="${dir.src.jni}" includes="${moduleName}.*" />
</delete>
<javah class="test.${moduleName}" outputFile="${dir.src.jni}/${moduleName}.h" classpath="${dir.classes}" />
<exec dir="${dir.src.jni}" executable="wine" os="Linux,Mac OS X">
<arg line="cmd /c bin\\cl -Ijdk_include -Ijdk_include\\win32 -I${moduleName} -MD -LD ${moduleName}\\${moduleName}.c -Fe${moduleName}.dll" />
</exec>
<exec dir="${dir.src.jni}" executable="cmd" os="Windows 95,Windows 98,Windows NT,Windows 2000,Windows XP,Windows Vista,Windows 7">
<arg line="/c bin\\cl -Ijdk_include -Ijdk_include\\win32 -I${moduleName} -MD -LD ${moduleName}\\${moduleName}.c -Fe${moduleName}.dll" />
</exec>
<copy todir="${dir.deploy}" overwrite="true" failonerror="false">
<fileset dir="${dir.src.jni}">
<include name="${moduleName}.dll" />
<include name="${moduleName}.lib" />
</fileset>
</copy>
<delete>
<fileset dir="${dir.src.jni}">
<include name="${moduleName}.*" />
</fileset>
</delete>
</target>
</project> - 執行build.xml,產生HelloWorld.dll:
如果想用MingGW,請服用:
- 取得MingGW:MinGW官網
$ wget http://sourceforge.net/projects/mingw/files/Automated%20MinGW%20Installer/mingw-get-inst/mingw-get-inst-20110316/mingw-get-inst-20110316.exe/download - 安裝MingGW:
$ wine <PATH-TO-DOWNLOAD-DIR>/mingw-get-inst-20110316.exe - 在Eclipse建立MINGW專案(General Project就可以了)
- 複製Compiler檔案:
$ cp -rvf ~/.wine/drive_c/MingGW/* <PATH-TO-MINGW-PROJECT> - 建立mingwenv.bat:
$ vi <PATH-TO-HELLOWORLDJNI-PROJECT>/src/jni/bin/mingwenv.bat
@echo off
set MINGW_HOME=..\..\..\mingw
set PATH=%MINGW_HOME%\bin;%MINGW_HOME%\mingw32\bin;%PATH%
- 建立gcc.bat:
$ vi <PATH-TO-HELLOWORLDJNI-PROJECT>/src/jni/bin/gcc.bat
echo off
@call bin\mingwenv.bat
gcc %* - 編輯build.xml:
$ vi <PATH-TO-HELLOWORLDJNI-PROJECT>/build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="Packaging Generator" default="all">
<property name="dir.src" value="src" />
<property name="dir.src.java" value="${dir.src}/java" />
<property name="dir.src.junit" value="${dir.src}/junit" />
<property name="dir.src.jni" value="${dir.src}/jni" />
<property name="dir.src.jdkinclude" value="${dir.src}/jni/jdk_include" />
<property name="dir.etc" value="etc" />
<property name="dir.lib" value="lib" />
<property name="dir.deploy" value="deploy" />
<property name="dir.classes" value="tmp" />
<property name="dir.build" value="build" />
<target name="all">
<antcall target="HelloWorld.dll" />
</target>
<target name="HelloWorld.dll">
<property name="moduleName" value="HelloWorld" />
<mkdir dir="${dir.deploy}" />
<delete>
<fileset dir="${dir.src.jni}" includes="${moduleName}.*" />
</delete>
<javah class="test.${moduleName}" outputFile="${dir.src.jni}/${moduleName}.h" classpath="${dir.classes}" />
<exec dir="${dir.src.jni}" executable="wine" os="Linux,Mac OS X">
<arg line="cmd /c bin\\gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -Ijdk_include -Ijdk_include\\win32 -I${moduleName} -shared ${moduleName}\\${moduleName}.c -o ${moduleName}.dll" />
</exec>
<exec dir="${dir.src.jni}" executable="cmd" os="Windows 95,Windows 98,Windows NT,Windows 2000,Windows XP,Windows Vista,Windows 7">
<arg line="/c bin\\gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -Ijdk_include -Ijdk_include\\win32 -I${moduleName} -shared ${moduleName}\\${moduleName}.c -o ${moduleName}.dll" />
</exec>
<copy todir="${dir.deploy}" overwrite="true" failonerror="false">
<fileset dir="${dir.src.jni}">
<include name="${moduleName}.dll" />
<include name="${moduleName}.lib" />
</fileset>
</copy>
<delete>
<fileset dir="${dir.src.jni}">
<include name="${moduleName}.*" />
</fileset>
</delete>
</target>
</project> - 執行build.xml,產生HelloWorld.dll:
如果想用Borland C++ 5.5,請服用:
- 取得Borland C++ 5.5:Codegear官網
- 安裝Borland C++ 5.5:
$ wine <PATH-TO-DOWNLOAD-DIR>/freecommandLinetools.exe - 在Eclipse建立BCC55專案(General Project就可以了)
- 複製Compiler檔案:
$ cp -rvf ~/.wine/drive_c/Borland/BCC55/* <PATH-TO-BCC55-PROJECT> - 建立bcc55env.bat:
$ vi <PATH-TO-HELLOWORLDJNI-PROJECT>/src/jni/bin/bcc55env.bat
@echo off
set BCC55_HOME=..\..\..\bcc55
set PATH=%BCC55_HOME%\bin;%PATH%
- 建立bcc32.bat:
$ vi <PATH-TO-HELLOWORLDJNI-PROJECT>/src/jni/bin/bcc32.bat
echo off
@call bin\bcc55env.bat
bcc32 %* - 編輯build.xml:
$ vi <PATH-TO-HELLOWORLDJNI-PROJECT>/build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="Packaging Generator" default="all">
<property name="dir.src" value="src" />
<property name="dir.src.java" value="${dir.src}/java" />
<property name="dir.src.junit" value="${dir.src}/junit" />
<property name="dir.src.jni" value="${dir.src}/jni" />
<property name="dir.src.jdkinclude" value="${dir.src}/jni/jdk_include" />
<property name="dir.etc" value="etc" />
<property name="dir.lib" value="lib" />
<property name="dir.deploy" value="deploy" />
<property name="dir.classes" value="tmp" />
<property name="dir.build" value="build" />
<target name="all">
<antcall target="HelloWorld.dll" />
</target>
<target name="HelloWorld.dll">
<property name="moduleName" value="HelloWorld" />
<mkdir dir="${dir.deploy}" />
<delete>
<fileset dir="${dir.src.jni}" includes="${moduleName}.*" />
</delete>
<javah class="test.${moduleName}" outputFile="${dir.src.jni}/${moduleName}.h" classpath="${dir.classes}" />
<exec dir="${dir.src.jni}" executable="wine" os="Linux,Mac OS X">
<arg line="cmd /c bin\\bcc32 -Ijdk_include -Ijdk_include\\win32 -I..\\..\\..\\bcc55\\Include -L..\\..\\..\\bcc55\\Lib -I${moduleName} -WD ${moduleName}\\${moduleName}.c -o${moduleName}.dll" />
</exec>
<exec dir="${dir.src.jni}" executable="cmd" os="Windows 95,Windows 98,Windows NT,Windows 2000,Windows XP,Windows Vista,Windows 7">
<arg line="/c bin\\bcc32 -Ijdk_include -Ijdk_include\\win32 -I..\\..\\..\\bcc55\\Include -L..\\..\\..\\bcc55\\Lib -I${moduleName} -WD ${moduleName}\\${moduleName}.c -o${moduleName}.dll" />
</exec>
<copy todir="${dir.deploy}" overwrite="true" failonerror="false">
<fileset dir="${dir.src.jni}">
<include name="${moduleName}.dll" />
<include name="${moduleName}.lib" />
</fileset>
</copy>
<delete>
<fileset dir="${dir.src.jni}">
<include name="${moduleName}.*" />
</fileset>
</delete>
</target>
</project>
- 執行build.xml,產生HelloWorld.dll:
No comments:
Post a Comment