[ODE] More DLL headaches, but hopefully solved

nlin@nlin.net nlin at nlin.net
Mon Jan 28 12:50:02 2002


--ELM717889811-14462-0_
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit

I checked out the latest CVS source and had to do some tweaking to get the
DLL to compile. There were still some NT/Win16 issues which needed hammering
out, but I think I have it under control. 

So, here is the current status of DLL compiling. 

- Use the make from MinGW, www.mingw.org.
- Do not use Cygnus make. This is because Cygnus make passes all commands
  to bash.exe before passing them on to command.com for execution.
  In passing the commands to bash.exe, commands get screwed up because
  bash.exe and command.com handle quotes and parentheses differently
  on the command line.
- MinGW does not use a separate bash.exe command shell, instead using
  the operating system's native shell. Under WinNT, as reported by Russ,
  the current CVS version apparently compiles as a DLL. Under Win98
  and presumably all 16-bit Windows versions, the LINK command fails
  because the command line is too long.
- To solve the command-line length problem, I changed the Makefile to
  use a list file containing all object filenames. As always, this
  sounds easy in theory, but making it flexibly work in practice (dynamically
  creating a list file from a makefile variable instead of hard-coding
  the list file) was a bit more work. I think as it stands now,
  the Makefile will work for Linux, Win16, and WinNT. I can't test NT
  myself, though.

Anyone else want to give this a shot to verify that it works? I checked
out the CVS source today (28 Jan 2002) and applied the patch as appended.

NOTE: Whether or not a list file is used is controlled by the parameter
"WINDOWS16". In the Makefile patch I am submitting, I have hard-coded
this to be 1 (true) in the top-level Makefile. This should actually be
located in one of the sub-makefiles in the config/ subdirectory, but I
left it in the top-level Makefile for now so users can easily test if the
Makefile works or not by swapping out one file.

Hope this helps someone else. It's caused me enough headaches.
-Norman

--ELM717889811-14462-0_
Content-Type: text/plain; charset=ISO-8859-1
Content-Disposition: attachment; filename=dlldiffs
Content-Description: /tmp/dlldiffs
Content-Transfer-Encoding: 7bit

*** Makefile.orig	Tue Jan 29 02:03:00 2002
--- Makefile	Tue Jan 29 03:22:42 2002
***************
*** 20,25 ****
--- 20,26 ----
  #                                                                       #
  #########################################################################
  
+ WINDOWS16=1
  USER_SETTINGS=config/user-settings
  include $(USER_SETTINGS)
  PLATFORM_MAKEFILE=config/makefile.$(PLATFORM)
***************
*** 120,125 ****
--- 121,168 ----
  ODE_OBJECTS=$(ODE_SRC:%.cpp=%$(OBJ)) $(ODE_PREGEN_OBJECTS)
  DRAWSTUFF_OBJECTS=$(DRAWSTUFF_SRC:%.cpp=%$(OBJ)) $(RESOURCE_FILE)
  
+ # side-effect variables causing creation of files containing lists of
+ # filenames to be linked, to work around command-line-length limitations
+ # on outdated 16-bit operating systems. because of command-line length
+ # limitations we cannot issue a link command with all object filenames
+ # specified (because this command is too long and overflows the command
+ # buffer), but instead must create a file containing all object filenames
+ # to be linked, and specify this list-file with @listfile on the command-line.
+ 
+ # the difficult part is doing this in a flexible way; we don't want to
+ # hard-code the to-be-linked object filenames in a file, but instead
+ # want to dynamically create a file containing a list of all object filenames
+ # within the $XXX_OBJECTS makefile variables. to do this, we use side-effect
+ # variables.
+ 
+ # idea: when these variables are EVALUATED (i.e. later during rule execution,
+ # not now during variable definition), they cause a SIDE EFFECT which creates
+ # a file with the list of all ODE object files. why the chicanery??? because
+ # if we have a command-line length limitation, no SINGLE command we issue will 
+ # be able to create a file containing all object files to be linked
+ # (because that command itself would need to include all filenames, making
+ # it too long to be executed). instead, we must use the gnu-make "foreach"
+ # function, combined - probably in an unintended way - with the "shell" 
+ # function. this is probably unintended because we are not using the "shell"
+ # function to return a string value for variable evaluation, but are instead 
+ # using the "shell" function to cause a side effect (appending of each filename
+ # to the filename-list-file).
+ 
+ # one possible snag is that, forbidding use of any external EXE utilities and
+ # relying only on the facilities provided by the outdated 16-bit operating system,
+ # there is no way to issue a SERIES of commands which append text to the end
+ # of a file WITHOUT adding newlines. therefore, the list of to-be-linked
+ # object files is separated by newlines in the list file. fortunately,
+ # the linker utility for this outdated 16-bit operating system accepts
+ # filenames on separate lines in the list file.
+ 
+ # remember: when we evaluate these variables later, this causes the creation
+ # of the appropriate list file.
+ ifeq ($(WINDOWS16),1)
+ SIDE_EFFECT_ODE_OBJLIST = $(foreach o,$(ODE_OBJECTS),$(shell echo $(o) >> odeobj.txt ))
+ SIDE_EFFECT_DRAWSTUFF_OBJLIST = $(foreach o,$(DRAWSTUFF_OBJECTS),$(shell echo $(o) >> dsobj.txt ))
+ endif
+ 
  # library file names
  ODE_LIB=$(LIBPATH)/$(LIB_PREFIX)$(ODE_LIB_NAME)$(LIB_SUFFIX)
  DRAWSTUFF_LIB=$(LIBPATH)/$(LIB_PREFIX)$(DRAWSTUFF_LIB_NAME)$(LIB_SUFFIX)
***************
*** 151,166 ****
  ODE_LIB_AR_RULE=$(AR)$@
  endif
  
! $(ODE_LIB): $(ODE_OBJECTS)
  	$(ODE_LIB_AR_RULE) $(ODE_OBJECTS)
  ifdef RANLIB
  	$(RANLIB) $@
  endif
  
! $(DRAWSTUFF_LIB): $(DRAWSTUFF_OBJECTS)
  	$(AR)$@ $(DRAWSTUFF_OBJECTS)
  ifdef RANLIB
  	$(RANLIB) $@
  endif
  
  clean:
--- 194,244 ----
  ODE_LIB_AR_RULE=$(AR)$@
  endif
  
! $(ODE_LIB): pre_ode_lib $(ODE_OBJECTS)
! ifeq ($(WINDOWS16),1)
! #     if we have a command-line-length limitation, then dynamically create
! #     a file containing all object filenames, and pass this file to the linker
! #     instead of directly specifying the object filenames on the command line
! 
! #     the very evaluation of the following variable causes creation of file odeobj.txt
! 	$(SIDE_EFFECT_ODE_OBJLIST)
! 	$(ODE_LIB_AR_RULE) @odeobj.txt
! else
! #     if we have no command-line-length limitation, directly specify all object files to be linked
  	$(ODE_LIB_AR_RULE) $(ODE_OBJECTS)
+ endif
+ 
  ifdef RANLIB
  	$(RANLIB) $@
  endif
  
! $(DRAWSTUFF_LIB): pre_drawstuff_lib $(DRAWSTUFF_OBJECTS)
! ifeq ($WINDOWS16),1)
! # if we have a command-line-length limitation, then dynamically create
! # a file containing all object filenames, and pass this file to the linker
! # instead of directly specifying the object filenames on the command line
! 
! # the very evaluation of the following variable causes creation of file dsobj.txt
! 	$(SIDE_EFFECT_DRAWSTUFF_OBJLIST)
! 	$(AR)$@ @dsobj.txt
! else
! # if we have no command-line-length limitation, directly specify all object files to be linked
  	$(AR)$@ $(DRAWSTUFF_OBJECTS)
+ endif
  ifdef RANLIB
  	$(RANLIB) $@
+ endif
+ 
+ # rules to be executed before library linking starts: delete list file (if one is used)
+ 
+ pre_ode_lib:
+ ifeq ($WINDOWS16),1)
+ 	$(DEL_CMD) odeobj.txt
+ endif
+ 
+ pre_drawstuff_lib:
+ ifeq ($WINDOWS16),1)
+ 	$(DEL_CMD) dsobj.txt
  endif
  
  clean:

--ELM717889811-14462-0_--