Wednesday, December 9, 2009

compile xerces-c & xalan-c on cygwin

Yet another cygwin log again. Since the unfamiliar with under surface details of how it works, whenever sometime wrong happens on cygwin, it'll be a nightmare. This time is the xerces-c & xalan-c.


Since recent project requires to use the xpath in c++, the only choice probably is the xalan-c. I did think that if the library of c++ become rich enough, everyone c++ worker will be much easier from a developer coming from enterprise computing language and script language perspective. = =

This time, the story goes like this, i need to compile the xerces-c 2.7 as xalan 1.1 compatibility. The original binary package for cygwin is 3.0.1-1 or 2.8.0-5 under Devel/libxerces-c-devel. The steps of compilation as the Readme.html said:
1. set the XERCESCROOT virable to the directory contains the extracting of xerces. for example ~/dev/xerces-c-src_2_7_0
2. go the the XERCESCROOT/src/xercesc, use ./runConfigure -pcygwin -cgcc -xg++ to make the Makefile (runConfigure is a helper script, we can use ./configure also)
3. if everything's done properly, just make it. and make install

My problem comes at the step 3, the make can not be processed when reaching the 'deprecated DOM part'. The Problem is the exactly the same as this bug report XERCESC-1501.
Creating library file: \ /cygdrive/d/tmp/xerces-c-src_2_7_0/lib/libxerces-depdom27.dll.a \ CYGWIN/depdom/AttrImpl.o(.text+0x4bb):AttrImpl.cpp: undefined reference to \ `xercesc_2_7::XMemory::operator delete(void*)' \ CYGWIN/depdom/AttrImpl.o(.text+0x50d):AttrImpl.cpp: undefined reference to \ `xercesc_2_7::XMemory::
...
...
... ::fgNoString' collect2: ld returned 1 exit status make[1]: *** [/cygdrive/d/tmp/xerces-c-src_2_7_0/lib/cygxerces-depdom27.dll] Error 1 make[1]: Target `ALL' not remade because of errors. make: *** [/cygdrive/d/tmp/xerces-c-src_2_7_0/lib/cygxerces-c27.dll] Error 2
 
The error seems saying the it can not find certain deprecated dom library. First, I went through the way this post said. After spending 1 hour to find where I can add that link options in the Makefile, the make still not work. 
Then I thought probably, it's the libxerces-c-devel problem. I uninstalled it. Then everything just works, with some auto-import warning, INFO.
After make install the compiled code, we can do test with the sample. The compilation of the sample works well. Everything works now.
Next, compilation of xalan-c. Nightmare again ...
1. set the XALANCROOT virable to the extracted xalan/c , make sure the XERCESCROOT is still there
2. in the XALANCROOT, run ./runConfigure -p cygwin -c gcc -x g++ -P /usr/local , make sure including the -P in order to use the 'make install'.
3. type 'make', here comes the problem, exactly the same as this one: http://marc.info/?l=xalan-c-users&m=115953899805021&w=2

make -C src/xalanc all make[1]: Entering directory `/usr/src/xml-xalan/c/src/xalanc' Preparing the directory structure for a build ... mkdir -p ../../obj mkdir -p ../../lib mkdir -p ../../bin make -C Utils prepare make[2]: Entering directory `/usr/src/xml-xalan/c/src/xalanc/Utils' Makefile:71: *** multiple target patterns.  Stop. make[2]: Leaving directory `/usr/src/xml-xalan/c/src/xalanc/Utils' make[1]: *** [prepare] Error 2 make[1]: Leaving directory `/usr/src/xml-xalan/c/src/xalanc' make: *** [all] Error 2
The thread is very interesting. The last one solved this problem partly: http://marc.info/?l=xalan-c-users&m=116048865019326&w=2
 
  
I could now compile Xalan.
The problem was the empty XLIFF_FILE_NAME.
I hard coded the Windows form of the file, "C:/cygwin/usr/....", to Utils/Makefile and changed the line
$(XSL_NLS_DIR)/include/LocalMsgData.hpp : $(XSL_BIN_DIR)/MsgCreator $(XLIFF_FILE_NAME) to
$(XSL_NLS_DIR)/include/LocalMsgData.hpp : $(XSL_BIN_DIR)/MsgCreator
But the "make install" fails:
 
Actually it says the problem is because the XLIFF_FILE_NAME has not been processed successfully, but with an empty string in the real make run. In order to fix that one, we need to set it manually in the Utils/Makefile.
1. In the line 38 of the Utils/Makefile, we can find the XLIFF_FILE_NAME for Cygwin. comment out that line, add add XLIFF_FILENAME=$XALANCROOT/src/xalanc/NLS/en_US/XalanMsg_en_US.xlf 
2. In the line 71, i found that keep it the same still can make successful. so what we need is do the step 1. 
 
I said the solution solves the problem partly, because when I make the xalan now, the result is not that stable, sometimes errors, sometimes successful, and everytime the errors are different. In the make output, After lots of g++ -O, it starts to create the .dll file. The problem here is sometimes, it says some *.o can not be found in obj/ . 
The time I successfully compiled it is I redirected the make output into a text file. = = Otherwise, different *.o are reported as can  not be found in different run. = = very wired.
 
Anyway, the compilation seems finished, then comes the 'make install'. 
 
  Remember when doing ./runConfigure, we should specify the -P as the installation directory. I set as /usr/local/ at the beginning. 
The make file will try to install the file at //usr/local//bin|lib|include, and // can not be recogonized by bash in cygwin. 
The solution is to modify the Makefile.incl at the root directory. Line 40, change 'prefix=/usr/local/' to 'prefix=usr/local'. I tried to rerun the runConfigure with -P usr/local, but it does not work because absolute path checking. 
 
Then the 'make install' works. 
 
Next nightmare to me, is the installation seems having something wrong. 
The cygxalan-c110.dll has been installed in /usr/local/lib, not in /usr/local/bin, and the cygxalanMsg110.dll has been kept in the XALANCROOT/lib, but not in /usr/local/bin
   
I compiled the samples by 'make samples' to see whether everything works. But the result is frustrating. only the MsgCreator.exe works, others said:
the procedure entry point AddAtomA could not be located in the dynamic link library cygwin1.dll
Googled the AddAtomA, it said that AddAtomA has been exported by kernal32.dll : http://www.pc1news.com/virus/function-addatoma-1177.html
  kernal32.dll is in C:\Windows\system32
but why cygwin1.dll can not locate that??

Thursday, August 27, 2009

Cygwin/X, cygwin with gui : )

Still using cygwin in the current project. These days the job is setting up a cygwin rails server with RMagick installed. On the RMagick FAQ page I read some information about setting up the cygwin/x, so I started, which makes this rainy afternoon interesting. : )
 
Cygwin/x makes x server run happily on windows. The install instruction is straightforward:
 
Cygwin/x comes with a xwin exe. When xwin started, it'll start a xserver integrated with a windows notification, which means you can use the xserver as other windows apps.
 
With startx command, we can start xserver using .xinitrc configuration. Using xterm started by xserver, we can use display and animate if we installed ImageMagick. Note: here is xterm, not the original cgwin shell winodw. If we start from there, we'll get an error : display: unable to open X server `'
 
btw, by installing the procps package, on cygwin, we can use the top on cygwin.

Friday, August 21, 2009

using SWIG + Cygwin + Ruby

Basiclly using swig+cygwin+ruby is not that hard. After reading first few pages from the manual, we can get up and start writing simple examples. However, the first example spends me a whole afternoon.
At first, SWIG seems a very inviting tool for me, since it provides the unified development process to deal with different languages integration with C/C++. Due to the project constraint, I can only use Cygwin to simulate Unix/Linux environment.
1. get swig from cygwin setup OR the windows version works also)
2. get ruby from cygwin setup, and download rubygems from rubyforge and install it at cygwin
3. write a simple test.c
int add(int a, int b) {
return a + b;
}
4. write a simple test.i
%module test
%{
extern int add(int a, int b);
%}
extern int add(int a, int b);
5. using swig to generate the wrapper, (if win version, add swig.exe to PATH, restart cygwin to read it)
swig -ruby test.i (if using cpp, swig -c++ -ruby test.i)
this will generate the test_wrap.c, don't forget -ruby mark, by default is tcl
6. compile the test.c test_wrap.c
gcc -c test.c test_wrap.c -I/usr/lib/ruby/1.8/i386-cygwin (or the right place having the ruby C h files)
this wil generate test.o, test_wrap.o
7. generate the dynamic library from .o
gcc -shared test.o test_wrap.o /usr/lib/libruby.dll.a -enable-auto-import -o test.so
if not auto import, this will complain about the auto complete config but will generate file correctly. after this, test.so will be generated.
8. use the irb to test it
start irb from the same directory
irb ... > require 'test' # test is .so file name
=> true
irb ... > puts Test.add(100, 101) # Test.add, Test is module name, should be capitalized.
201
=> nil
that's it.
Here's the tricky points:
1. ruby problem, better install the cygwin version ruby, for me the ruby at windows, when compile report error about mismatch versions of ms windows
2. ruby gems problem, if you don't install ruby gem sperately at cygwin, start ruby program, you'll get some error like 'ubygems could not find .. '. That's because the RUBYOPT environment usually is set by one click installer at windows. The cygwin ruby can see it also, it'll try to find the rubygems program at /usr/lib/ruby/..., but at cygwin rubygems is not installed by default.
3. when compiling, the ruby header files locations
the manual said at /usr/local/include/ruby ...
at cygwin, it's at /usr/lib/ruby/1.8/i386-cygwin
4. when linking, the ruby library locations
the manual does not include it at all, if you use that, you'll get lots of errors like '_rb_error undefined ...'
for ruby 1.8.x, the cygwin path of it is /usr/lib/libruby.dll.a
libruby-static.a is not the right one
don't use the windows version linking library, which is at C:\Ruby\lib\msvcrt-ruby18.lib, use it you'll get lots of errors. that's for ms vc linker.
5. most trickiest, when the module name should be capitalized. (spend most of the afternoon here!!)
irb ..> require 'test'
=> true
irb ..> puts test.add(100, 101)
undefined test ...
should be Test.add(100, 101)
at last. everything finally works. = =!!!
The capitalized problem made me confused a lot, since the references for using swig+ruby+cygwin is not that much, you need to have question at each step ...
btw: Ctrl + L at cygwin console can have the 'cls' function. : ) just got to know ...

Wednesday, August 5, 2009

gcc's [Undefined reference to 'vtable for ...'] error handling

I did not touch c++ ooad at least 4 years ... after some standization, the language looks good though, still not that comfortable to me so far. due to some project requirement, i'm struggling with c++ ooad these days. after drawing class chart, i spent lots of time to pick up the ooad features, rules and conventions in cpp.
one of the wired thing today, is after i added some virtual function to some class hierachy, gcc linker reports 'Undefined reference to 'vtable for ...' . after googling, i found this is a gcc feature or limitation or specific implementation towards the iso standard.
here's the official solution: http://gcc.gnu.org/faq.html#vtables
well, i do believe after spending enough time on this language, i'll be much more comfortable with it. hope so ~ ^^

Tuesday, August 4, 2009

fancy auto dependency generation?? = =

i encountered some error from g++ today said 'undefined reference to xx method'
the compiler actually said, it can not find the implementation of this method, which means the file may not be compiled.
that's true.
i checked the makefile which i adopted from some open source project. it uses advanced auto dependency generation to check needed files .. however, the dependency generator can only finds the .h file, but it'll not compile the .cpp file. ==
i modified the makefile, everything works fine now. = = however, 2hrs just vanished ...

Friday, July 31, 2009

how to deal with bit stream or bit set in cpp

what's a byte: uint8_t
containers: bitset vs vector<bool>
how to print: hex, dec, oct, in std namespace. all have lasting effects which is confusing at some time.
note char = 'A' does not mean 0xA

Friday, July 24, 2009

how to set cygwin bash environment

to set up the environment variables in cygwin, we need to edit the c:\cygwin\Cygwin.bat, not the .bashrc
the cygwin user's guide seems a good resource for working with cygwin: