diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c9da9de6be..f9103e9310 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,11 +1,8 @@ function(add_example name) set(target_name ${name}_example) add_executable(${target_name} ${name}.c) - target_include_directories(${target_name} PRIVATE - ${PROJECT_SOURCE_DIR}/include - ) - target_link_libraries(${target_name} - secp256k1 + target_link_libraries(${target_name} PRIVATE + libsecp256k1::secp256k1 $<$:bcrypt> ) set(test_name ${name}_example) diff --git a/include/secp256k1.h b/include/secp256k1.h index 1d25a02ab2..d9bee89d50 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -121,45 +121,21 @@ typedef int (*secp256k1_nonce_function)( #endif /* Symbol visibility. */ -#if defined(_WIN32) - /* GCC for Windows (e.g., MinGW) accepts the __declspec syntax - * for MSVC compatibility. A __declspec declaration implies (but is not - * exactly equivalent to) __attribute__ ((visibility("default"))), and so we - * actually want __declspec even on GCC, see "Microsoft Windows Function - * Attributes" in the GCC manual and the recommendations in - * https://gcc.gnu.org/wiki/Visibility. */ -# if defined(SECP256K1_BUILD) -# if defined(DLL_EXPORT) || defined(SECP256K1_DLL_EXPORT) - /* Building libsecp256k1 as a DLL. - * 1. If using Libtool, it defines DLL_EXPORT automatically. - * 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */ -# define SECP256K1_API extern __declspec (dllexport) -# else - /* Building libsecp256k1 as a static library on Windows. - * No declspec is needed, and so we would want the non-Windows-specific - * logic below take care of this case. However, this may result in setting - * __attribute__ ((visibility("default"))), which is supposed to be a noop - * on Windows but may trigger warnings when compiling with -flto due to a - * bug in GCC, see - * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116478 . */ -# define SECP256K1_API extern -# endif - /* The user must define SECP256K1_STATIC when consuming libsecp256k1 as a static - * library on Windows. */ -# elif !defined(SECP256K1_STATIC) - /* Consuming libsecp256k1 as a DLL. */ -# define SECP256K1_API extern __declspec (dllimport) -# endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define SECP256K1_EXPORT __declspec(dllexport) +# define SECP256K1_IMPORT __declspec(dllimport) +#else +# define SECP256K1_EXPORT __attribute__((visibility("default"))) +# define SECP256K1_IMPORT __attribute__((visibility("default"))) #endif #ifndef SECP256K1_API -/* All cases not captured by the Windows-specific logic. */ -# if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD) - /* Building libsecp256k1 using GCC or compatible. */ -# define SECP256K1_API extern __attribute__ ((visibility ("default"))) -# else - /* Fall back to standard C's extern. */ -# define SECP256K1_API extern -# endif +# if defined(SECP256K1_STATIC) +# define SECP256K1_API extern +# elif defined(SECP256K1_BUILD) +# define SECP256K1_API extern SECP256K1_EXPORT +# else +# define SECP256K1_API extern SECP256K1_IMPORT +# endif #endif /* Warning attributes diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8f1d2ee3ba..a14f5cf8cc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,9 @@ add_library(secp256k1) +# Allow projects in the same source tree to use this as if it had been imported. +# The prefix has to match the NAMESPACE in `install(EXPORT)` further down. +add_library(${PROJECT_NAME}::secp256k1 ALIAS secp256k1) + set_property(TARGET secp256k1 PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1.h ${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h @@ -54,40 +58,24 @@ add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL # from being exported. target_sources(secp256k1 PRIVATE secp256k1.c $) -# Create a helper lib that parent projects can use to link secp256k1 into a -# static lib. -add_library(secp256k1_objs INTERFACE) -target_sources(secp256k1_objs INTERFACE $ $) - -add_library(secp256k1_asm INTERFACE) if(SECP256K1_ASM STREQUAL "arm32") - add_library(secp256k1_asm_arm OBJECT EXCLUDE_FROM_ALL) - target_sources(secp256k1_asm_arm PUBLIC - asm/field_10x26_arm.s - ) - target_sources(secp256k1 PRIVATE $) - target_sources(secp256k1_objs INTERFACE $) - target_link_libraries(secp256k1_asm INTERFACE secp256k1_asm_arm) + add_library(secp256k1_asm OBJECT EXCLUDE_FROM_ALL asm/field_10x26_arm.s) +else() + add_library(secp256k1_asm INTERFACE) endif() -if(WIN32) - # Define our export symbol only for shared libs. - set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL SECP256K1_DLL_EXPORT) - target_compile_definitions(secp256k1 INTERFACE $<$>:SECP256K1_STATIC>) -endif() +# When building a static libary, SECP256K1_STATIC must be defined both for itself and downstream. +# Note that the generator expression is evaluated in the context of the consuming target! +target_compile_definitions(secp256k1 PUBLIC $<$,STATIC_LIBRARY>:SECP256K1_STATIC>) +set_target_properties(secp256k1 PROPERTIES C_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON) # Object libs don't know if they're being built for a shared or static lib. # Grab the PIC property from secp256k1 which knows. get_target_property(use_pic secp256k1 POSITION_INDEPENDENT_CODE) set_target_properties(secp256k1_precomputed PROPERTIES POSITION_INDEPENDENT_CODE ${use_pic}) -# Add the include path for parent projects so that they don't have to manually add it. -target_include_directories(secp256k1 INTERFACE - $>:${PROJECT_SOURCE_DIR}/include>> -) -set_target_properties(secp256k1_objs PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "$" -) +# Add the include path for projects in the same source tree. +target_include_directories(secp256k1 INTERFACE $) # This emulates Libtool to make sure Libtool and CMake agree on the ABI version, # see below "Calculate the version variables" in build-aux/ltmain.sh. @@ -123,18 +111,21 @@ if(SECP256K1_BUILD_BENCHMARK) add_executable(bench bench.c) target_link_libraries(bench secp256k1) add_executable(bench_internal bench_internal.c) + target_compile_definitions(bench_internal PRIVATE $) target_link_libraries(bench_internal secp256k1_precomputed secp256k1_asm) add_executable(bench_ecmult bench_ecmult.c) + target_compile_definitions(bench_ecmult PRIVATE $) target_link_libraries(bench_ecmult secp256k1_precomputed secp256k1_asm) endif() if(SECP256K1_BUILD_TESTS) add_executable(noverify_tests tests.c) + target_compile_definitions(noverify_tests PRIVATE $) target_link_libraries(noverify_tests secp256k1_precomputed secp256k1_asm) add_test(NAME secp256k1_noverify_tests COMMAND noverify_tests) if(NOT CMAKE_BUILD_TYPE STREQUAL "Coverage") add_executable(tests tests.c) - target_compile_definitions(tests PRIVATE VERIFY) + target_compile_definitions(tests PRIVATE VERIFY $) target_link_libraries(tests secp256k1_precomputed secp256k1_asm) add_test(NAME secp256k1_tests COMMAND tests) endif() @@ -144,7 +135,10 @@ if(SECP256K1_BUILD_EXHAUSTIVE_TESTS) # Note: do not include secp256k1_precomputed in exhaustive_tests (it uses runtime-generated tables). add_executable(exhaustive_tests tests_exhaustive.c) target_link_libraries(exhaustive_tests secp256k1_asm) - target_compile_definitions(exhaustive_tests PRIVATE $<$>:VERIFY>) + target_compile_definitions(exhaustive_tests PRIVATE + $<$>:VERIFY> + $ + ) add_test(NAME secp256k1_exhaustive_tests COMMAND exhaustive_tests) endif()