summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJukka Ojanen <jukka.ojanen@linkotec.net>2015-11-30 17:16:01 +0200
committerJukka Ojanen <jukka.ojanen@linkotec.net>2015-11-30 17:18:31 +0200
commitae1b59ddd07cb66b0807bc2c7c981ce96c69acea (patch)
tree0b17e0271543e1fb897aba27c242b656378df858
parentc3e325911ae15524c814db75fe701df91d6f7c2a (diff)
downloadffts-ae1b59ddd07cb66b0807bc2c7c981ce96c69acea.zip
ffts-ae1b59ddd07cb66b0807bc2c7c981ce96c69acea.tar.gz
Enable building shared library and start version numbering from 0.9.0. On Windows when using FFTS as a DLL, define FFTS_SHARED. This is not mandatory, but it offers a little performance increase. Hide symbols when possible to improve compiler optimization and sizeof binary. Use CMake target alias "ffts" to choose between static and shared library, preferring static
-rw-r--r--CMakeLists.txt97
-rw-r--r--include/ffts.h43
-rw-r--r--src/ffts.c8
-rw-r--r--src/ffts_nd.c6
-rw-r--r--src/ffts_real.c2
-rw-r--r--src/ffts_real_nd.c6
6 files changed, 134 insertions, 28 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6536ef0..6c72b5b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,6 +2,13 @@ cmake_minimum_required(VERSION 2.8)
project(ffts C ASM)
+# TODO: to support AutoConfigure building, this should came from "template" file
+set(FFTS_MAJOR 0)
+set(FFTS_MINOR 9)
+set(FFTS_MICRO 0)
+
+set(FFTS_VERSION "ffts-${FFTS_MAJOR}.${FFTS_MINOR}.${FFTS_MICRO}")
+
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@@ -27,15 +34,25 @@ option(ENABLE_RUNTIME_DYNAMIC_CODE
"Enables the runtime generation of dynamic machine code." ON
)
+option(GENERATE_POSITION_INDEPENDENT_CODE
+ "Generate position independent code" OFF
+)
+
option(ENABLE_SHARED
"Enable building a shared library." OFF
)
+option(ENABLE_STATIC
+ "Enable building a static library." ON
+)
+
include(CheckCSourceCompiles)
include(CheckCSourceRuns)
include(CheckIncludeFile)
-add_definitions(-DFFTS_CMAKE_GENERATED)
+# Ensure defined when building FFTS (as opposed to using it from
+# another project). Used to export functions from Windows DLL.
+add_definitions(-DFFTS_BUILD)
# check existence of various headers
check_include_file(malloc.h HAVE_MALLOC_H)
@@ -286,13 +303,24 @@ if(MSVC)
# enable all warnings but also disable some..
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /wd4127")
+ # mark debug versions
+ set(CMAKE_DEBUG_POSTFIX "d")
+
add_definitions(-D_USE_MATH_DEFINES)
elseif(CMAKE_COMPILER_IS_GNUCC)
+ include(CheckCCompilerFlag)
include(CheckLibraryExists)
# enable all warnings
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
+ # check if we can control visibility of symbols
+ check_c_compiler_flag(-fvisibility=hidden HAVE_GCC_VISIBILITY)
+ if(HAVE_GCC_VISIBILITY)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
+ add_definitions(-DHAVE_GCC_VISIBILITY)
+ endif(HAVE_GCC_VISIBILITY)
+
# some systems need libm for the math functions to work
check_library_exists(m pow "" HAVE_LIBM)
if(HAVE_LIBM)
@@ -385,16 +413,61 @@ else()
)
endif(DISABLE_DYNAMIC_CODE)
-add_library(ffts_static
- ${FFTS_HEADERS}
- ${FFTS_SOURCES}
-)
+if(GENERATE_POSITION_INDEPENDENT_CODE)
+ if(CMAKE_VERSION VERSION_LESS "2.8.9")
+ check_c_compiler_flag(-fPIC HAVE_GCC_PIC)
+ if(HAVE_GCC_PIC)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -DPIC")
+ check_c_compiler_flag(-fPIE HAVE_GCC_PIE)
+ if(HAVE_GCC_PIE)
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -DPIE")
+ endif(HAVE_GCC_PIE)
+ endif(HAVE_GCC_PIC)
+ else()
+ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+ endif(CMAKE_VERSION VERSION_LESS "2.8.9")
+endif(GENERATE_POSITION_INDEPENDENT_CODE)
+
+if(ENABLE_SHARED)
+ add_library(ffts_shared SHARED
+ ${FFTS_HEADERS}
+ ${FFTS_SOURCES}
+ )
-add_executable(ffts_test
- tests/test.c
-)
+ # On unix-like platforms the library is called "libffts.so" and on Windows "ffts.dll"
+ set_target_properties(ffts_shared PROPERTIES
+ DEFINE_SYMBOL FFTS_SHARED
+ OUTPUT_NAME ffts
+ VERSION ${FFTS_MAJOR}.${FFTS_MINOR}.${FFTS_MICRO}
+ )
+endif(ENABLE_SHARED)
-target_link_libraries(ffts_test
- ffts_static
- ${FFTS_EXTRA_LIBRARIES}
-)
+if(ENABLE_STATIC)
+ add_library(ffts_static STATIC
+ ${FFTS_HEADERS}
+ ${FFTS_SOURCES}
+ )
+
+ if(UNIX)
+ # On unix-like platforms the library is called "libffts.a"
+ set_target_properties(ffts_static PROPERTIES OUTPUT_NAME ffts)
+ endif(UNIX)
+endif(ENABLE_STATIC)
+
+if(ENABLE_STATIC OR ENABLE_SHARED)
+ add_executable(ffts_test
+ tests/test.c
+ )
+
+ # link with static library by default
+ if(ENABLE_STATIC)
+ add_library(ffts ALIAS ffts_static)
+ else()
+ add_library(ffts ALIAS ffts_shared)
+ endif(ENABLE_STATIC)
+
+ target_link_libraries(ffts_test
+ ffts
+ ${FFTS_EXTRA_LIBRARIES}
+ )
+endif(ENABLE_STATIC OR ENABLE_SHARED)
diff --git a/include/ffts.h b/include/ffts.h
index 8e25cb4..d187e36 100644
--- a/include/ffts.h
+++ b/include/ffts.h
@@ -42,27 +42,54 @@
extern "C" {
#endif
+#if (defined(_WIN32) || defined(WIN32)) && defined(FFTS_SHARED)
+# ifdef FFTS_BUILD
+# define FFTS_API __declspec(dllexport)
+# else
+# define FFTS_API __declspec(dllimport)
+# endif
+#else
+# if (__GNUC__ >= 4) || defined(HAVE_GCC_VISIBILITY)
+# define FFTS_API __attribute__ ((visibility("default")))
+# else
+# define FFTS_API
+# endif
+#endif
+
#define POSITIVE_SIGN 1
#define NEGATIVE_SIGN -1
struct _ffts_plan_t;
typedef struct _ffts_plan_t ffts_plan_t;
-ffts_plan_t *ffts_init_1d(size_t N, int sign);
-ffts_plan_t *ffts_init_2d(size_t N1, size_t N2, int sign);
-ffts_plan_t *ffts_init_nd(int rank, size_t *Ns, int sign);
+FFTS_API ffts_plan_t*
+ffts_init_1d(size_t N, int sign);
+
+FFTS_API ffts_plan_t*
+ffts_init_2d(size_t N1, size_t N2, int sign);
+
+FFTS_API ffts_plan_t*
+ffts_init_nd(int rank, size_t *Ns, int sign);
/* For real transforms, sign == -1 implies a real-to-complex forwards tranform,
and sign == 1 implies a complex-to-real backwards transform.
The output of a real-to-complex transform is N/2+1 complex numbers,
where the redundant outputs have been omitted.
*/
-ffts_plan_t *ffts_init_1d_real(size_t N, int sign);
-ffts_plan_t *ffts_init_2d_real(size_t N1, size_t N2, int sign);
-ffts_plan_t *ffts_init_nd_real(int rank, size_t *Ns, int sign);
+FFTS_API ffts_plan_t*
+ffts_init_1d_real(size_t N, int sign);
+
+FFTS_API ffts_plan_t*
+ffts_init_2d_real(size_t N1, size_t N2, int sign);
+
+FFTS_API ffts_plan_t*
+ffts_init_nd_real(int rank, size_t *Ns, int sign);
+
+FFTS_API void
+ffts_execute(ffts_plan_t *p, const void *input, void *output);
-void ffts_execute(ffts_plan_t *p, const void *input, void *output);
-void ffts_free(ffts_plan_t *p);
+FFTS_API void
+ffts_free(ffts_plan_t *p);
#ifdef __cplusplus
}
diff --git a/src/ffts.c b/src/ffts.c
index a04a92c..a22a1c8 100644
--- a/src/ffts.c
+++ b/src/ffts.c
@@ -149,7 +149,8 @@ static FFTS_INLINE void ffts_vmem_free(void *addr, size_t length)
#endif
}
-void ffts_execute(ffts_plan_t *p, const void *in, void *out)
+FFTS_API void
+ffts_execute(ffts_plan_t *p, const void *in, void *out)
{
/* TODO: Define NEEDS_ALIGNED properly instead */
#if defined(HAVE_SSE) || defined(HAVE_NEON)
@@ -165,7 +166,8 @@ void ffts_execute(ffts_plan_t *p, const void *in, void *out)
p->transform(p, (const float*) in, (float*) out);
}
-void ffts_free(ffts_plan_t *p)
+FFTS_API void
+ffts_free(ffts_plan_t *p)
{
if (p) {
p->destroy(p);
@@ -409,7 +411,7 @@ cleanup:
return -1;
}
-ffts_plan_t*
+FFTS_API ffts_plan_t*
ffts_init_1d(size_t N, int sign)
{
const size_t leaf_N = 8;
diff --git a/src/ffts_nd.c b/src/ffts_nd.c
index 23338c1..72e21e7 100644
--- a/src/ffts_nd.c
+++ b/src/ffts_nd.c
@@ -281,7 +281,8 @@ static void ffts_execute_nd(ffts_plan_t *p, const void *in, void *out)
}
}
-ffts_plan_t *ffts_init_nd(int rank, size_t *Ns, int sign)
+FFTS_API ffts_plan_t*
+ffts_init_nd(int rank, size_t *Ns, int sign)
{
ffts_plan_t *p;
size_t vol;
@@ -354,7 +355,8 @@ cleanup:
return NULL;
}
-ffts_plan_t *ffts_init_2d(size_t N1, size_t N2, int sign)
+FFTS_API ffts_plan_t*
+ffts_init_2d(size_t N1, size_t N2, int sign)
{
size_t Ns[2];
diff --git a/src/ffts_real.c b/src/ffts_real.c
index 6650d07..7f41069 100644
--- a/src/ffts_real.c
+++ b/src/ffts_real.c
@@ -599,7 +599,7 @@ ffts_execute_1d_real_inv(ffts_plan_t *p, const void *input, void *output)
p->plans[0]->transform(p->plans[0], buf, output);
}
-ffts_plan_t*
+FFTS_API ffts_plan_t*
ffts_init_1d_real(size_t N, int sign)
{
ffts_plan_t *p;
diff --git a/src/ffts_real_nd.c b/src/ffts_real_nd.c
index 5eae44b..545e8f0 100644
--- a/src/ffts_real_nd.c
+++ b/src/ffts_real_nd.c
@@ -218,7 +218,8 @@ static void ffts_execute_nd_real_inv(ffts_plan_t *p, const void *in, void *out)
}
}
-ffts_plan_t *ffts_init_nd_real(int rank, size_t *Ns, int sign)
+FFTS_API ffts_plan_t*
+ffts_init_nd_real(int rank, size_t *Ns, int sign)
{
int i;
size_t vol = 1;
@@ -327,7 +328,8 @@ cleanup:
return NULL;
}
-ffts_plan_t *ffts_init_2d_real(size_t N1, size_t N2, int sign)
+FFTS_API ffts_plan_t*
+ffts_init_2d_real(size_t N1, size_t N2, int sign)
{
size_t Ns[2];
OpenPOWER on IntegriCloud