[CMake] shared and static libs with same rootname (was: Two questions)

Brandon J. Van Every bvanevery at gmail.com
Mon Aug 14 16:18:57 EDT 2006


Jorge Rodriguez wrote:
> 1) Is there any way to build a target library as static and shared, 
> with the same name?

If you are building on WIN32, MinGW and Cygwin are both bugged in CMake 
2.4.3.  They cannot generate both static and shared libraries with the 
same rootname.  They delete each other's files during the build, leaving 
you with only one or the other.  So, in CMake 2.4.3 libfoo.a and 
libfoo.dll.a cannot coexist.  I am informed that this has been fixed in 
CMake CVS, but I have not had time to test this myself.  If the fix is 
good, then CMake 2.4.4 will not have this problem.

I do not know if the problem exists on other platforms, like Linux, 
which do not have dlls.

In any event, the *target* names must be unique.  For instance my actual 
targets are chicken, libchicken, and libchicken-static.  You use 
SET_TARGET_PROPERTIES to change what the OUTPUT_NAME name will be.  I've 
attached the relevant sections of Chicken's CMakeLists.txt, as they are 
a fairly clear example of CMake 2.4.3 naming problems and workarounds on 
Windows.


Cheers,
Brandon Van Every


# We want the library to be named 'libchicken' on all platforms.
# But, Cygwin conspires against us.  Their convention is
# cygname-0.dll and so forth.  Whether it's a "best practice" is
# debateable, but in the Cygwin FAQ and Googling about, it's the
# practice. 
# Default Unix, Cygwin, and MinGW behavior is to add 'lib' as a
# prefix onto every library.  For cross-platform stuff,
# this often results in the 'liblibfoo" problem.

# Let CMake do the prefixing magic on Unix, Cygwin, and MinGW.

IF(CYGWIN)
  SET_TARGET_PROPERTIES(libchicken PROPERTIES OUTPUT_NAME chicken-0)
  SET_TARGET_PROPERTIES(libuchicken PROPERTIES OUTPUT_NAME uchicken-0)
ELSE(CYGWIN)
  SET_TARGET_PROPERTIES(libchicken PROPERTIES OUTPUT_NAME chicken)
  SET_TARGET_PROPERTIES(libuchicken PROPERTIES OUTPUT_NAME uchicken)
ENDIF(CYGWIN)
IF(MSVC OR MINGW)
  SET_TARGET_PROPERTIES(libchickengui PROPERTIES OUTPUT_NAME chickengui)
ENDIF(MSVC OR MINGW)

# CMake 2.4.3 has a bug where libchicken.a and libchicken.dll.a
# clobber each other during the build.  This will be fixed in
# CMake 2.4.4 and then we can have both at the same time.
# Meanwhile as a workaround we need to distinguish the library names
# and do a symlink at install time.

IF(MINGW)
  SET_TARGET_PROPERTIES(libchicken-static PROPERTIES OUTPUT_NAME chicken-s)
  SET_TARGET_PROPERTIES(libuchicken-static PROPERTIES OUTPUT_NAME 
uchicken-s)
  SET_TARGET_PROPERTIES(libchickengui-static PROPERTIES OUTPUT_NAME 
chickengui-s)
ELSE(MINGW)
  SET_TARGET_PROPERTIES(libchicken-static PROPERTIES OUTPUT_NAME chicken)
  SET_TARGET_PROPERTIES(libuchicken-static PROPERTIES OUTPUT_NAME uchicken)
  IF(MSVC)
    SET_TARGET_PROPERTIES(libchickengui-static PROPERTIES OUTPUT_NAME 
chickengui)
  ENDIF(MSVC)
ENDIF(MINGW)

# Unix-y compilers tack "lib" onto the front of library names.  MSVC 
doesn't.
# Also, MSVC uses the indistinguishable suffix .lib for both dlls and static
# libraries.  So we need postfixes to distinguish our library names.
# Can't find any canonical postfixing conventions, so these will do for now.
# Don't wish to use "-m" for MINSIZEREL_POSTFIX because "mt" typically means
# "multithreaded, static linkage" for Windows native libraries.

IF(MSVC)
  SET_TARGET_PROPERTIES(libchicken PROPERTIES PREFIX "lib" IMPORT_PREFIX 
"lib"
    RELEASE_POSTFIX "" MINSIZEREL_POSTFIX "-z" DEBUG_POSTFIX "-d" 
RELWITHDEBINFO_POSTFIX "-g")
  SET_TARGET_PROPERTIES(libuchicken PROPERTIES PREFIX "lib" 
IMPORT_PREFIX "lib"
    RELEASE_POSTFIX "" MINSIZEREL_POSTFIX "-z" DEBUG_POSTFIX "-d" 
RELWITHDEBINFO_POSTFIX "-g")
  SET_TARGET_PROPERTIES(libchickengui PROPERTIES PREFIX "lib" 
IMPORT_PREFIX "lib"
    RELEASE_POSTFIX "" MINSIZEREL_POSTFIX "-z" DEBUG_POSTFIX "-d" 
RELWITHDEBINFO_POSTFIX "-g")
  SET_TARGET_PROPERTIES(libuchicken-static PROPERTIES PREFIX "lib"
    RELEASE_POSTFIX "-s" MINSIZEREL_POSTFIX "-sz" DEBUG_POSTFIX "-sd" 
RELWITHDEBINFO_POSTFIX "-sg")
  SET_TARGET_PROPERTIES(libchicken-static PROPERTIES PREFIX "lib"
    RELEASE_POSTFIX "-s" MINSIZEREL_POSTFIX "-sz" DEBUG_POSTFIX "-sd" 
RELWITHDEBINFO_POSTFIX "-sg")
  SET_TARGET_PROPERTIES(libchickengui-static PROPERTIES PREFIX "lib"
    RELEASE_POSTFIX "-s" MINSIZEREL_POSTFIX "-sz" DEBUG_POSTFIX "-sd" 
RELWITHDEBINFO_POSTFIX "-sg")
ENDIF(MSVC)

# CMake 2.4.3 will collide libchicken.dll.a and libchicken.a.
# We symlink around the problem until CMake 2.4.4 ships.

# CMake 2.4.3 can't produce both cygchicken-0.dll and libchicken.dll.a
# Currently Autoconf must produce the cygchicken-0.dll nomenclature,
# and that name is needed internally by the libraries for things to
# work correctly, so we can't ditch it in the source pool.  So we
# symlink it here.  This workaround courtesy of John Cowan.

# Cygwin CMake 2.4.3 has "cmake -E create_symlink"
# MinGW CMake 2.4.3 does not, as it is Windows native.
# MSYS has "ln -s" but it only does a copy, not an actual
# symlink.  Also MinGW isn't necessarily using MSYS.  All
# said and done, MinGW gets a straight copy and we hope it works.

# Brad King demonstrated \$ENV{DESTDIR} as the preferred method
# of handling ${CMAKE_INSTALL_PREFIX} when doing INSTALL(CODE ...)
# But I don't think this can be supported, as the paths must be
# hardwired into Chicken itself.

IF(MINGW)
  INSTALL(CODE "
    MESSAGE(STATUS \"Copying libchicken-s.a to libchicken.a\")
    EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E remove
      \"${LIB_HOME}/libchicken.a\")
    EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E copy
      \"${LIB_HOME}/libchicken-s.a\"
      \"${LIB_HOME}/libchicken.a\")
    MESSAGE(STATUS \"Copying libuchicken-s.a to libuchicken.a\")
    EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E remove
      \"${LIB_HOME}/libuchicken.a\")
    EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E copy
      \"${LIB_HOME}/libuchicken-s.a\"
      \"${LIB_HOME}/libuchicken.a\")
    MESSAGE(STATUS \"Copying libchickengui-s.a to libchickengui.a\")
    EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E remove
      \"${LIB_HOME}/libchickengui.a\")
    EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E copy
      \"${LIB_HOME}/libchickengui-s.a\"
      \"${LIB_HOME}/libchickengui.a\")
  ")
ENDIF(MINGW)

IF(CYGWIN)
  INSTALL(CODE "
    MESSAGE(STATUS \"Symlinking libchicken-0.dll.a to libchicken.dll.a\")
    EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E remove
      \"${LIB_HOME}/libchicken.dll.a\")
    EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E create_symlink
      \"${LIB_HOME}/libchicken-0.dll.a\"
      \"${LIB_HOME}/libchicken.dll.a\")
    MESSAGE(STATUS \"Symlinking libuchicken-0.dll.a to libuchicken.dll.a\")
    EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E remove
      \"${LIB_HOME}/libuchicken.dll.a\")
    EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E create_symlink
      \"${LIB_HOME}/libuchicken-0.dll.a\"
      \"${LIB_HOME}/libuchicken.dll.a\")
  ")
ENDIF(CYGWIN)





More information about the CMake mailing list