Project

General

Profile

Actions

Task #2243

closed

Allow building of shared library

Added by Alex Afanasyev over 9 years ago. Updated almost 9 years ago.

Status:
Closed
Priority:
Normal
Category:
Build
Target version:
Start date:
Due date:
% Done:

100%

Estimated time:

Description

Right now ndn-cxx is compiled as a static library. This was done in attempt to reduce problems when library ABI changes (which is basically any time there is any change to header files). Right now, the library is relatively stable, so it is beneficial to compile the library as dynamic one.

We still need to keep compilation as a static library, at least as an option. This is needed on some platforms, for example on Android.


One subtle issue with static compilation affects ndnSIM effort. With static library, each linked unit (another shared lib, an app) has its own copy of the variables that controls selection of the custom clocks. As a result, setCustomClocks method called inside the scenario (an app) has different effect from calling the same method inside the helper class (part of ndnSIM shared lib).


Related issues 2 (1 open1 closed)

Related to ndn-cxx - Bug #2853: Global variable in static library causes double free or corruption errorRejected06/05/2015

Actions
Blocks ndn-cxx - Feature #2859: Explicitly export public symbolsNew

Actions
Actions #1

Updated by Alex Afanasyev over 9 years ago

  • Category changed from Base to Build
Actions #2

Updated by Junxiao Shi over 9 years ago

  • Subject changed from Switch compilation to shared library (keeping static library as an option) to Compile as shared library by default
  • Start date deleted (11/30/2014)
Actions #3

Updated by Alex Afanasyev almost 9 years ago

  • Status changed from New to Code review
  • % Done changed from 0 to 100
Actions #5

Updated by Junxiao Shi almost 9 years ago

Compiling as shared library is good.
But making shared library as the default is a breaking change.
https://travis-ci.org/yoursunny/ndn-cxx-breaks/builds/65342104

For a Ubuntu source code deployment, the ndn-cxx shared library is installed to /usr/local/lib.
When a program (eg. NFD) linked with this shared library is loaded, the system does not look for the shared library object in /usr/local/lib unless this path is set in LD_LIBRARY_PATH environment variable.

Therefore, I suggest proceeding in multiple steps:

  1. introduce the option to compile as shared library, but keep the default as static object
  2. adjust all affected deployments:
    • send a "breaking change notification" to ndn-lib and nfd-dev to notify users
    • modify instructions, manuals, documents, build scripts of all owned projects to set (or educate users to set) LD_LIBRARY_PATH
  3. change the default to static compilation
Actions #6

Updated by Davide Pesavento almost 9 years ago

After this change, will the ndn-cxx-dev deb package continue to install the static lib?

Junxiao Shi wrote:

* modify instructions, manuals, documents, build scripts of all owned projects to set (or educate users to set) `LD_LIBRARY_PATH`

That, or rpath in the executable.

Actions #7

Updated by Alex Afanasyev almost 9 years ago

After this change, will the ndn-cxx-dev deb package continue to install the static lib?

I'm planning to switch to shared library for the package.

* modify instructions, manuals, documents, build scripts of all owned projects to set (or educate users to set) `LD_LIBRARY_PATH`

That, or rpath in the executable.

Based on some posts, rpath is not that recommended way. Just in case, on OSX each library already has "rpath" embedded, so things become partially simpler (no need to ldconfig or define LD_LIBRARY_PATH), but partially more complicated (need to run ./waf install before running unit tests).

Actions #8

Updated by Alex Afanasyev almost 9 years ago

Compiling as shared library is good.
But making shared library as the default is a breaking change.
https://travis-ci.org/yoursunny/ndn-cxx-breaks/builds/65342104

This is not a breaking change. The problem is with test script, not the dependent projects. Simply run ldconfig after installing the library and error will be gone.

For a Ubuntu source code deployment, the ndn-cxx shared library is installed to /usr/local/lib.
When a program (eg. NFD) linked with this shared library is loaded, the system does not look for the shared library object in /usr/local/lib unless this path is set in LD_LIBRARY_PATH environment variable.

/usr/local/lib is normally present in the library load path. The exception that I know is Fedora, which requires either what you said or adding /usr/local/lib into /etc/ld.so.conf.d/

Therefore, I suggest proceeding in multiple steps:

  1. introduce the option to compile as shared library, but keep the default as static object
  2. adjust all affected deployments:
    • send a "breaking change notification" to ndn-lib and nfd-dev to notify users
    • modify instructions, manuals, documents, build scripts of all owned projects to set (or educate users to set) LD_LIBRARY_PATH
  3. change the default to static compilation

I could go with this approach, but not 100% convinced yet that it is necessary.

Actions #9

Updated by Davide Pesavento almost 9 years ago

Alex Afanasyev wrote:

After this change, will the ndn-cxx-dev deb package continue to install the static lib?

I'm planning to switch to shared library for the package.

Sure, but libndn-cxx.so goes into ndn-cxx package... I was asking if you intended to keep the static archive in the -dev package or not.

That, or rpath in the executable.

Based on some posts, rpath is not that recommended way. Just in case, on OSX each library already has "rpath" embedded, so things become partially simpler (no need to ldconfig or define LD_LIBRARY_PATH), but partially more complicated (need to run ./waf install before running unit tests).

Yes, rpath is strongly discouraged by some distros for installed packages. But packages will install the lib into /usr/lib anyway, so there's no problem in this case. The rpath is still useful (and is more convenient than LD_LIBRARY_PATH) for running ndn-cxx unit tests for example.

For reverse dependencies not using binary packages (i.e. dev environments): the pkgconfig file should take care of supplying the build-time library path, and for the runtime path, as you said most distros already include /usr/local/lib in their ld.so.conf. So this will be an issue only for those running Fedora (or similar distros) and compiling everything themselves. I think documenting the need for LD_LIBRARY_PATH is enough to solve these cases.

Actions #10

Updated by Alex Afanasyev almost 9 years ago

After this change, will the ndn-cxx-dev deb package continue to install the static lib?

I'm planning to switch to shared library for the package.

Sure, but libndn-cxx.so goes into ndn-cxx package... I was asking if you intended to keep the static archive in the -dev package or not.

Sorry, I misread the question. I wasn't planning to include static library, but I don't have a strong preference.

Actions #11

Updated by Davide Pesavento almost 9 years ago

I'm fine either way. I just wanted to know so that I can do the same in the Gentoo ebuilds.

Actions #12

Updated by Junxiao Shi almost 9 years ago

But making shared library as the default is a breaking change.
https://travis-ci.org/yoursunny/ndn-cxx-breaks/builds/65342104

This is not a breaking change. The problem is with test script, not the dependent projects. Simply run ldconfig after installing the library and error will be gone.

Original documentation of either ndn-cxx and NFD/NLSR does not mention ldconfig.
If ldconfig becomes necessary, this is a breaking change.

Actions #13

Updated by Alex Afanasyev almost 9 years ago

Davide:

what's the soname of the library?

The current logic that is built into waf scripts is

  • (for ELF) to assign SONAME as <library-name>.so.<MAJOR> (libndn-cxx.so.0), which as I understand assumes that ABI stays the same with minor/patch changes.

  • (for Mach-O) to use install-name <install-path>/<library-name>.dylib (/usr/local/lib/libndn-cxx.dylib). I think this is a bug, which we can fix in our version and report upstream.


Now question is what is best for us. Obviously, using libndn-cxx.so.0 (or /usr/local/lib/libndn-cxx.0.dylib after the fix) is not a good solution for us, as we are breaking ABI all the time with each minor and "patch" release.

My suggestion, with assumption that we will always break ABI with each release, is to hack waf to set:

  • (for ELF) SONAME to <library-name>.so.<MAJOR>.<MINOR>.<PATCH> (libndn-cxx.so.0.3.2)

  • (for Mach-O) install-name to <install-path>/<library-name>.<MAJOR>.<MINOR>.<PATCH>.dylib (/usr/local/lib/libndn-cxx.0.3.2.dylib)

Actions #14

Updated by Davide Pesavento almost 9 years ago

Alex Afanasyev wrote:

My suggestion, with assumption that we will always break ABI with each release, is to hack waf to set:

  • (for ELF) SONAME to <library-name>.so.<MAJOR>.<MINOR>.<PATCH> (libndn-cxx.so.0.3.2)

Yes this is definitely doable (openssl does more or less the same). Alternatively we can use the "libtool approach" to soname versioning, but I find it less intuitive and it requires a little more maintenance in our case, so I prefer the openssl approach.

Btw, are you sure you have to hack waf to implement this? the soname is a very basic feature of shared libraries, I'd be surprised if waf doesn't allow client code to pass the soname as parameter...

  • (for Mach-O) install-name to <install-path>/<library-name>.<MAJOR>.<MINOR>.<PATCH>.dylib (/usr/local/lib/libndn-cxx.0.3.2.dylib)

I don't care about OS X and I don't know much about the Mach-O format, so I don't know whether this is going to break something or not. But I guess not, since by putting the version before .dylib you're basically making it part of the library basename. If you want to be sure, use a hyphen before the version instead of a dot, i.e. libndn-cxx-0.3.2.dylib (glib does this, but for a different reason than ours).

Actions #15

Updated by Alex Afanasyev almost 9 years ago

  • Target version changed from v0.3 to v0.4

I just submitted a pull request for waf: https://github.com/waf-project/waf/pull/1583

Based on my understanding, there were some hard-coded not user-configurable parts.


Preliminary, will change waf to this version (https://github.com/cawka/waf/commit/2b3bb0af33c07b93a72803a332ea8286427006bc), which is just adding my patch on top of previous version (no waf version upgrade).

Actions #16

Updated by Davide Pesavento almost 9 years ago

Btw, for several good reasons we should also add -fvisibility=hidden and -fvisibility-inlines-hidden to the shared lib's default CXXFLAGS, and explicitly export all public types (we can use a macro for this).

Actions #17

Updated by Chengyu Fan almost 9 years ago

  • Related to Bug #2853: Global variable in static library causes double free or corruption error added
Actions #18

Updated by Alex Afanasyev almost 9 years ago

Just in case. My pull request was merged to the waf upstream.

Actions #19

Updated by Alex Afanasyev almost 9 years ago

Btw, for several good reasons we should also add -fvisibility=hidden and -fvisibility-inlines-hidden to the shared lib's default CXXFLAGS, and explicitly export all public types (we can use a macro for this).

I'm not sure I have expertise with this and cannot estimate how much work it would require. We can keep the current issue open or create another one specifically for these options.

Actions #20

Updated by Junxiao Shi almost 9 years ago

Actions #21

Updated by Alex Afanasyev almost 9 years ago

Huh.. Apparently, we need to use -fPIC for static library. With the change I made, ndnSIM stops compiling on some platforms:

/usr/bin/ld: /usr/local/lib/libndn-cxx.a(data.cpp.2.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/libndn-cxx.a: error adding symbols: Bad value
Actions #22

Updated by Davide Pesavento almost 9 years ago

Alex Afanasyev wrote:

Huh.. Apparently, we need to use -fPIC for static library. With the change I made, ndnSIM stops compiling on some platforms:

You need to link against the shared version of ndn-cxx obviously. Non-PIC code cannot be used in shared libraries (except on x86_32, but even there it's a kludge).

Actions #23

Updated by Alex Afanasyev almost 9 years ago

Yeah. I'm updating the test scripts and documentation of ndnSIM for that.

Actions #24

Updated by Alex Afanasyev almost 9 years ago

  • Status changed from Code review to Closed
Actions #25

Updated by Davide Pesavento almost 9 years ago

uh? the default is still static as far as I can see.

Actions #26

Updated by Alex Afanasyev almost 9 years ago

  • Subject changed from Compile as shared library by default to Allow building of shared library

Oops. I'll separate the issue.

Actions

Also available in: Atom PDF