Discussion:
[CMake] static & shared library
Doug Henry
2005-08-03 11:37:17 UTC
Permalink
is it possible to build a static and shared library (without re-running
cmake) for the same target? Something like:

ADD_LIBRARY(target STATIC ...)
ADD_LIBRARY(target SHARED ...)

cmake doesn't allow add_library twice for the same target, so it sort of
makes sense that the above doesn't work, even though they create different
files. Any info appreciated.

-doug
David Cole
2005-08-03 12:20:40 UTC
Permalink
Not in general. You'll want two distinct binary trees for this. On some
platforms, the compile stage is different for the two types of
libraries. And on Windows, specifically, creating a shared library (dll)
also produces an import library (lib) which clients of the library need
to link to. So, if you tried to build both, you'd end up with two
target.lib files (one the "real" static lib and one an import lib which
links the client to the dll) and somebody somewhere would get confused...

Is there a problem with "re-running cmake"? And using two separate
binary directories, one for static, one for shared? (Other than the fact
that your build has to be twice as long when you have two binary trees
to produce...)

HTH,
David
Post by Doug Henry
is it possible to build a static and shared library (without
ADD_LIBRARY(target STATIC ...)
ADD_LIBRARY(target SHARED ...)
cmake doesn't allow add_library twice for the same target, so it sort
of makes sense that the above doesn't work, even though they create
different files. Any info appreciated.
-doug
------------------------------------------------------------------------
_______________________________________________
CMake mailing list
http://www.cmake.org/mailman/listinfo/cmake
Doug Henry
2005-08-03 12:30:02 UTC
Permalink
thanks. its not a real problem, but if I didn't have to compile twice that
would obviously be better :-) Right now I just tack on -static to the target
name and have two targets. I'm basically trying to loosely simulate the
autotools functionality where you can independently switch on/off shared and
static (--disable-shared --enable-static).
Post by David Cole
Not in general. You'll want two distinct binary trees for this. On some
platforms, the compile stage is different for the two types of
libraries. And on Windows, specifically, creating a shared library (dll)
also produces an import library (lib) which clients of the library need
to link to. So, if you tried to build both, you'd end up with two
target.lib files (one the "real" static lib and one an import lib which
links the client to the dll) and somebody somewhere would get confused...
Is there a problem with "re-running cmake"? And using two separate
binary directories, one for static, one for shared? (Other than the fact
that your build has to be twice as long when you have two binary trees
to produce...)
HTH,
David
Post by Doug Henry
is it possible to build a static and shared library (without
ADD_LIBRARY(target STATIC ...)
ADD_LIBRARY(target SHARED ...)
cmake doesn't allow add_library twice for the same target, so it sort
of makes sense that the above doesn't work, even though they create
different files. Any info appreciated.
-doug
------------------------------------------------------------------------
_______________________________________________
CMake mailing list
http://www.cmake.org/mailman/listinfo/cmake
William A. Hoffman
2005-08-03 12:41:10 UTC
Permalink
thanks. its not a real problem, but if I didn't have to compile twice that would obviously be better :-) Right now I just tack on -static to the target name and have two targets. I'm basically trying to loosely simulate the autotools functionality where you can independently switch on/off shared and static (--disable-shared --enable-static).
I think you want the BUILD_SHARED_LIBS flag. If you add the libraries without specifying static or
shared, then the global BUILD_SHARED_LIBS is used instead. This works just like autoconfs --enable-shared
and --enable-static.


ADD_LIBRARY: Add an library to the project using the specified source files.

ADD_LIBRARY(libname [SHARED | STATIC | MODULE]
source1 source2 ... sourceN)

Adds a library target. SHARED, STATIC or MODULE keywords are used to set the library type. If the keyword MODULE appears, the library type is set to MH_BUNDLE on systems which use dyld. On systems without dyld, MODULE is treated like SHARED. If no keywords appear as the second argument, the type defaults to the current value of BUILD_SHARED_LIBS. If this variable is not set, the type defaults to STATIC.


-Bill
Doug Henry
2005-08-03 15:17:39 UTC
Permalink
right, but I think static/shared are mutually exclusive. I can't choose
static and shared, which I can with autotools.
Post by Doug Henry
thanks. its not a real problem, but if I didn't have to compile twice
that would obviously be better :-) Right now I just tack on -static to the
target name and have two targets. I'm basically trying to loosely simulate
the autotools functionality where you can independently switch on/off shared
and static (--disable-shared --enable-static).
I think you want the BUILD_SHARED_LIBS flag. If you add the libraries
without specifying static or
shared, then the global BUILD_SHARED_LIBS is used instead. This works just
like autoconfs --enable-shared
and --enable-static.
ADD_LIBRARY: Add an library to the project using the specified source files.
ADD_LIBRARY(libname [SHARED | STATIC | MODULE]
source1 source2 ... sourceN)
Adds a library target. SHARED, STATIC or MODULE keywords are used to set
the library type. If the keyword MODULE appears, the library type is set to
MH_BUNDLE on systems which use dyld. On systems without dyld, MODULE is
treated like SHARED. If no keywords appear as the second argument, the type
defaults to the current value of BUILD_SHARED_LIBS. If this variable is not
set, the type defaults to STATIC.
-Bill
William A. Hoffman
2005-08-03 15:28:27 UTC
Permalink
Yes, that is correct, although many autotools projects I have seen work the way cmake does.
I guess you could do something like this:


SET(FOO_SRCS ...)
ADD_LIBRARY(fooStatic STATIC ${FOO_SRCS})
ADD_LIBRARY(fooShared SHARED ${FOO_SRCS})
SET_TARGET_PROPERTIES(fooStatic fooShared PROPERTIES OUTPUT_NAME foo)

I am not sure TARGET_LINK_LIBRARIES would work correctly, but it would
build a libfoo.so and a libfoo.a in the same build.

-Bill
right, but I think static/shared are mutually exclusive. I can't choose static and shared, which I can with autotools.
thanks. its not a real problem, but if I didn't have to compile twice that would obviously be better :-) Right now I just tack on -static to the target name and have two targets. I'm basically trying to loosely simulate the autotools functionality where you can independently switch on/off shared and static (--disable-shared --enable-static).
I think you want the BUILD_SHARED_LIBS flag. If you add the libraries without specifying static or
shared, then the global BUILD_SHARED_LIBS is used instead. This works just like autoconfs --enable-shared
and --enable-static.
ADD_LIBRARY: Add an library to the project using the specified source files.
ADD_LIBRARY(libname [SHARED | STATIC | MODULE]
source1 source2 ... sourceN)
Adds a library target. SHARED, STATIC or MODULE keywords are used to set the library type. If the keyword MODULE appears, the library type is set to MH_BUNDLE on systems which use dyld. On systems without dyld, MODULE is treated like SHARED. If no keywords appear as the second argument, the type defaults to the current value of BUILD_SHARED_LIBS. If this variable is not set, the type defaults to STATIC.
-Bill
_______________________________________________
CMake mailing list
http://www.cmake.org/mailman/listinfo/cmake
Brad King
2005-08-03 17:51:38 UTC
Permalink
Post by William A. Hoffman
Yes, that is correct, although many autotools projects I have seen work the way cmake does.
SET(FOO_SRCS ...)
ADD_LIBRARY(fooStatic STATIC ${FOO_SRCS})
ADD_LIBRARY(fooShared SHARED ${FOO_SRCS})
SET_TARGET_PROPERTIES(fooStatic fooShared PROPERTIES OUTPUT_NAME foo)
I am not sure TARGET_LINK_LIBRARIES would work correctly, but it would
build a libfoo.so and a libfoo.a in the same build.
In CMake 2.2 this will probably not work. The link line generated by
the makefile generator now removes all possible names for a library
(shared, static, versioned shared, etc.) before linking the final
library. The reason is that if someone using BUILD_SHARED_LIBS switches
from shared to static then the static library will get built but unless
the shared is removed then linking to the library will choose the
out-of-date shared one.

For the same reason it is tricky to have a shared and static library
with the same name in the same directory in one's build tree. I
personally think it is generally a bad idea to have a shared and static
library with the same name because one then needs complicated linker
flags to choose the proper library:

cc -o myexe myexe.o -lmylib_static

versus

cc -o myexe myexe.o -Wl,-Bstatic -lmylib -Wl,-Bshared

and of course those -Wl,-B options are platform-specific.

-Brad
William A. Hoffman
2005-08-03 18:04:35 UTC
Permalink
In CMake 2.2 this will probably not work. The link line generated by the makefile generator now removes all possible names for a library (shared, static, versioned shared, etc.) before linking the final library. The reason is that if someone using BUILD_SHARED_LIBS switches from shared to static then the static library will get built but unless the shared is removed then linking to the library will choose the out-of-date shared one.
It will work as long as you don't set LIBRARY_OUTPUT_PATH. However, that being said,
if you are on windows it is impossible to have a shared and static with the same name
go into the same directory. For the shared case foo.dll and foo.lib are created, and
for the static case foo.lib is created. The two foo.lib files are very different.

-Bill
Brad King
2005-08-03 21:32:07 UTC
Permalink
Post by William A. Hoffman
Yes, that is correct, although many autotools projects I have seen work the way cmake does.
SET(FOO_SRCS ...)
ADD_LIBRARY(fooStatic STATIC ${FOO_SRCS})
ADD_LIBRARY(fooShared SHARED ${FOO_SRCS})
SET_TARGET_PROPERTIES(fooStatic fooShared PROPERTIES OUTPUT_NAME foo)
I am not sure TARGET_LINK_LIBRARIES would work correctly, but it would
build a libfoo.so and a libfoo.a in the same build.
There are two other reasons this will not work:

1.) OUTPUT_NAME is only available in CMake 2.2, not 2.0
2.) OUTPUT_NAME is only implemented for ADD_EXECUTABLE targets

-Brad

Loading...