radmedres / clmedview

An attempt to create a cross-platform medical image viewer specialized in drawing "regions of interests".
GNU General Public License v3.0
3 stars 2 forks source link

Proposal: Restructure project for shared libraries #29

Closed roelj closed 9 years ago

roelj commented 9 years ago

The current project structure compiles each component in the lib/ directory as objects and links them into one executable, clmedview. Every file is compiled from a single Makefile, except for the plugins.

While the code is separated quite clearly into libraries, the build system is currently not treating them as libraries. This has led to some ugly work-arounds in the plugin system (#include "dependency.c").

To make better use of, and to exploit the goodness of the separation of libraries we should be compiling to shared libraries and then link the libraries into the main executable. When doing so, the plugin system could simply link the libraries of the dependencies instead of recompiling the source code for them.

I've tried to restructure the project to see if this is feasible, and I found a way to do it. Here's my proposal for it:

/                   # Project root
libcommon           # libcommon-*.so
libconfiguration    # libconfiguration.so
libpixeldata        # libpixeldata.so and libpixeldata-plugin.so
...                 # For each library a directory containing a subproject.
source/             # Same as the current source folder.
                    # We could rename this to "clmedview/" for clarity.

Inside each library folder the structure is:

src/                # Contains the source files.
include/            # Contains the public interface header files.
Makefile.am         # Contains the build instructions for the libraries.

The Makefile.am for libcommon looks like this:

AUTOMAKE_OPTIONS              = subdir-objects
AM_CFLAGS                     = -Iinclude/

lib_LTLIBRARIES               = libcommon-algebra.la    \
                                libcommon-debug.la      \
                                libcommon-history.la    \
                                libcommon-list.la       \
                                libcommon-tree.la

libcommon_algebra_la_LDFLAGS  = -module -no-undefined -avoid-version
libcommon_algebra_la_SOURCES  = src/libcommon-algebra.c

libcommon_debug_la_LDFLAGS    = -module -no-undefined -avoid-version
libcommon_debug_la_SOURCES    = src/libcommon-debug.c

libcommon_history_la_LDFLAGS  = -module -no-undefined -avoid-version
libcommon_history_la_SOURCES  = src/libcommon-history.c

libcommon_list_la_LDFLAGS     = -module -no-undefined -avoid-version
libcommon_list_la_SOURCES     = src/libcommon-list.c

libcommon_tree_la_LDFLAGS     = -module -no-undefined -avoid-version
libcommon_tree_la_SOURCES     = src/libcommon-tree.c

With this project structure, we can split the build process in smaller parts (each library has its own Makefile), which cleans up the big Makefile.am in the root of the project.

Because each library is compiled into a shared object, all code only has to be compiled once to compile the entire program. And because of this, the work-around stuff in the plugin system can be cleaned up.

Possibly a drawback of this approach is that the project structure changes. The central include/ folder will be gone, and instead each library gets its own include/ folder. I think the proposed structure better displays the beauty of the separated components. Other than beauty, dependency management can be controlled at Makefile level, instead of source-file level.

Some intentional breakage is the removal of the - after lib. So lib-common is now named libcommon, which follows the standard naming schemes for libraries and allows one to ommit lib entirely when linking (-lcommon).

I'd like to apply these modifications and provide a compilable project after committing the changes. I currently separated libcommon, libpixeldata and libconfiguration, and the resulting executable is the same. To achieve this I configured the build system to link internal libraries statically.

minovations commented 9 years ago

Hey Roel,

I agree with making seperate libs, great.

I propose to create a folder structure like: lib/ lib/lib-dicom lib/lib-memory etc

within each dir a structure like: ...../src ....../include ....../obj

radmedres commented 9 years ago

Done