Skip to content

Commit e7cfb2e

Browse files
committed
Issues fixed surrounding the shared/dynamic library build
1. For some reason, CMake refuses to add the requisit linker flags (`-Wl,-rpath,/path/to/dylib`) when building executables against the imported dylib on Mac OS X and the Intel compilers. gfortran 4.9 seems to not trigger this CMake bug for some reason. Still investigating. 1. An option is present to select absolute install_name_dir vs @rpath on Mac when building the dylib. Since some issues with @rpath and CMake persist the `INSTALL_NAME_DIR` property is used rather than `@rpath` 1. However, if `DESTDIR=...` is defined when you `make install` the install name dir set at congigure time is no longer correct. Some install time CMake code was added to help fix this. 1. Some cached properties controling the build behavior were re- named to enable better grouping in `cmake-gui` and `ccmake`
1 parent 601d70e commit e7cfb2e

File tree

4 files changed

+86
-36
lines changed

4 files changed

+86
-36
lines changed

CMakeLists.txt

Lines changed: 73 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ set_property ( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYP
1919

2020

2121
enable_language ( Fortran )
22-
include ( cmake/pickFortranCompilerFlags.cmake )
22+
include ( "cmake/pickFortranCompilerFlags.cmake" )
2323

2424
# Check for in-source builds and error out if found
2525
# Provides an advanced option to allow in source builds
@@ -39,6 +39,8 @@ set ( VERSION_MINOR 0 )
3939
set ( VERSION_PATCH 0 )
4040
set ( VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" )
4141

42+
set ( PROJ_VERSION "${CMAKE_PROJECT_NAME}-${VERSION}" )
43+
4244
#-------------------------------------
4345
# Collect source files for the library
4446
#-------------------------------------
@@ -55,9 +57,45 @@ set ( JF_LIB_SRCS src/json_module.f90 )
5557
# libraries.
5658
set ( CMAKE_Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/include" )
5759

60+
#-------------------------------------
61+
# Define where our files get installed
62+
#-------------------------------------
63+
# Most of this is probably 'wrong' for Windows/Cygwin
64+
65+
if ( ${CMAKE_SYSTEM_NAME} MATCHES "Linux" )
66+
include ( GNU_Install_Dirs ) # Standard CMake module
67+
elseif ( UNIX ) #Apple, BSD, solaris, other *NIX? Framework on Apple instead?
68+
set ( CMAKE_INSTALL_LIBDIR lib )
69+
set ( CMAKE_INSTALL_INCLUDEDIR include )
70+
set ( CMAKE_INSTALL_DATAROOTDIR share )
71+
endif ( ${CMAKE_SYSTEM_NAME} MATCHES "Linux" )
72+
73+
# Set the package name to be specific to the compiler used, so that
74+
# versions compiled with different compilers can be installed in parallel
75+
string ( TOLOWER ${CMAKE_PROJECT_NAME}-${CMAKE_Fortran_COMPILER_ID} PACKAGE_NAME )
76+
string ( TOLOWER fortran/${CMAKE_Fortran_COMPILER_ID}-compiler FCOMPILER_DIR )
77+
78+
if ( "${CMAKE_SYSTEM_NAME}" MATCHES "Darwin" )
79+
set ( ENABLE_DYLIBS_USE_RPATH TRUE CACHE BOOL
80+
"Enable @rpath install name for dylibs" )
81+
mark_as_advanced ( ENABLE_DYLIBS_USE_RPATH )
82+
endif ( "${CMAKE_SYSTEM_NAME}" MATCHES "Darwin" )
83+
84+
if ( ENABLE_DYLIBS_USE_RPATH )
85+
if ( "${CMAKE_Fortran_COMPILER_ID}" MATCHES "Intel" )
86+
message ( WARNING
87+
"CMake bug may cause problems linking against dylibs compiled with ifort and installed using @rpath" )
88+
endif ( "${CMAKE_Fortran_COMPILER_ID}" MATCHES "Intel" )
89+
set ( CMAKE_MACOSX_RPATH FALSE )
90+
else ( ENABLE_DYLIBS_USE_RPATH )
91+
set ( CMAKE_INSTALL_NAME_DIR
92+
"\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${FCOMPILER_DIR}" )
93+
endif ( ENABLE_DYLIBS_USE_RPATH )
94+
5895
#---------------------------------------------
5996
# Build a shared and static library by default
6097
#---------------------------------------------
98+
6199
set ( LIB_NAME ${CMAKE_PROJECT_NAME} )
62100
add_library ( ${LIB_NAME} SHARED ${JF_LIB_SRCS} )
63101
add_library ( ${LIB_NAME}-static STATIC ${JF_LIB_SRCS} )
@@ -68,35 +106,45 @@ set_target_properties ( ${LIB_NAME}-static
68106
VERSION ${VERSION} )
69107
set_target_properties ( ${LIB_NAME}
70108
PROPERTIES
71-
SOVERSION ${VERSION_MAJOR}.${VERSION_MINOR} )
109+
OUTPUT_NAME ${LIB_NAME}
110+
PREFIX lib
111+
SOVERSION ${VERSION_MAJOR}.${VERSION_MINOR}
112+
VERSION ${VERSION} )
72113

73114
#---------------------------------------------------------------------
74115
# Add some tests to ensure that the software is performing as expected
75116
#---------------------------------------------------------------------
76117

77-
78-
#-------------------------------------
79-
# Define where our files get installed
80-
#-------------------------------------
81-
82-
if ( ${CMAKE_SYSTEM_NAME} MATCHES "Linux" )
83-
include ( GNU_Install_Dirs ) # Standard CMake module
84-
elseif ( UNIX ) #Apple, BSD, solaris, other *NIX? Framework on Apple instead?
85-
set ( CMAKE_INSTALL_LIBDIR lib )
86-
set ( CMAKE_INSTALL_INCLUDEDIR include )
87-
set ( CMAKE_INSTALL_DATAROOTDIR share )
88-
endif ( ${CMAKE_SYSTEM_NAME} MATCHES "Linux" )
89-
90-
# Set the package name to be specific to the compiler used, so that
91-
# versions compiled with different compilers can be installed in parallel
92-
string ( TOLOWER ${CMAKE_PROJECT_NAME}-${CMAKE_Fortran_COMPILER_ID} PACKAGE_NAME )
118+
#-------------------------
119+
# Perform the installation
120+
#-------------------------
93121

94122
install ( TARGETS ${LIB_NAME} ${LIB_NAME}-static
95123
EXPORT ${PACKAGE_NAME}-targets
96-
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/fortran/${CMAKE_Fortran_COMPILER_ID}-compiler"
97-
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}/fortran/${CMAKE_Fortran_COMPILER_ID}-compiler" )
98-
99-
set ( INSTALL_MOD_DIR "${CMAKE_INSTALL_INCLUDEDIR}/fortran/${CMAKE_Fortran_COMPILER_ID}-compiler" )
124+
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/${FCOMPILER_DIR}"
125+
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}/${FCOMPILER_DIR}" )
126+
#?ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}/${FCOMPILER_DIR}/${CMAKE_PROJECT_NAME}-${VERSION}"
127+
128+
# The following is some serious hackery and there's likely a better way
129+
# That better way is RPATH but bugs in CMake when using the Intel compiler persist
130+
# (-Wl,-rpath,/path/to/dylib does not get passed when compiling against imported dylib)
131+
set( ABS_LIB_INSTALL_DIR "\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${FCOMPILER_DIR}" )
132+
if ( NOT ENABLE_DYLIBS_USE_RPATH )
133+
if ( CMAKE_INSTALL_NAME_TOOL ) # On Mac and have install_name_tool
134+
install ( CODE "
135+
if ( DEFINED ENV{DESTDIR} )
136+
string ( REGEX REPLACE \"/$\" \"\" DESTDIR \"\$ENV{DESTDIR}\" ) # strip trailing /
137+
get_filename_component ( _install_path \${DESTDIR}/${ABS_LIB_INSTALL_DIR}
138+
ABSOLUTE )
139+
execute_process ( COMMAND
140+
${CMAKE_INSTALL_NAME_TOOL} -id \${_install_path} \${_install_path}/lib${LIB_NAME}.${VERSION}.dylib)
141+
endif ( DEFINED ENV{DESTDIR} )" )
142+
endif ( CMAKE_INSTALL_NAME_TOOL )
143+
endif ( NOT ENABLE_DYLIBS_USE_RPATH )
144+
145+
146+
147+
set ( INSTALL_MOD_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${FCOMPILER_DIR}/${PROJ_VERSION}" )
100148
install ( DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY}/ DESTINATION "${INSTALL_MOD_DIR}" )
101149

102150
#------------------------------------------
@@ -157,8 +205,8 @@ configure_file (
157205
${CMAKE_BINARY_DIR}/${PACKAGE_NAME}-config.cmake
158206
@ONLY )
159207

160-
set ( ADD_BUILD_TREE_TO_REGISTRY CACHE BOOL TRUE
208+
set ( ENABLE_BUILD_TREE_IN_REGISTRY FALSE CACHE BOOL
161209
"Add the ${PACKAGE_NAME} build tree to the CMake package registry?" )
162-
if ( ADD_BUILD_TREE_TO_REGISTRY )
210+
if ( ENABLE_BUILD_TREE_IN_REGISTRY )
163211
export ( PACKAGE ${PACKAGE_NAME} )
164-
endif ( ADD_BUILD_TREE_TO_REGISTRY )
212+
endif ( ENABLE_BUILD_TREE_IN_REGISTRY )

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ find_package ( jsonfortran-${CMAKE_Fortran_COMPILER_ID} 1.0.0 REQUIRED )
4343
add_executable ( json_example src/json_example.f90 )
4444
target_include_directories ( json_example BEFORE PUBLIC ${jsonfortran_INCLUDE_DIRS} )
4545
target_link_libraries ( json_example jsonfortran-static )
46+
# or for linking against the dynamic/shared library:
47+
# target_link_libraries ( json_example jsonfortran ) # instead
4648
```
4749

4850
Reading a JSON file

cmake/checkOutOfSource.cmake

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
option ( ALLOW_IN_SOURCE_BUILDS
1+
option ( ENABLE_IN_SOURCE_BUILDS
22
"Allow in source builds? Do so at your own risk, only if you know what you are doing. We STRONGLY advise against in source builds."
33
OFF )
4-
mark_as_advanced ( ALLOW_IN_SOURCE_BUILDS )
4+
mark_as_advanced ( ENABLE_IN_SOURCE_BUILDS )
55
get_filename_component ( FULL_BUILD_DIR "${CMAKE_BINARY_DIR}" REALPATH )
66
get_filename_component ( FULL_SOURCE_DIR "${CMAKE_SOURCE_DIR}" REALPATH )
77
if ( "${FULL_BUILD_DIR}" STREQUAL "${FULL_SOURCE_DIR}" )
8-
if ( ALLOW_IN_SOURCE_BUILDS )
8+
if ( ENABLE_IN_SOURCE_BUILDS )
99
message ( WARNING
1010
"Caution, in source build detected, procede at your own risk. Build and source directories are the same: ${CMAKE_SOURCE_DIR}" )
11-
else ( ALLOW_IN_SOURCE_BUILDS )
11+
else ( ENABLE_IN_SOURCE_BUILDS )
1212
message ( SEND_ERROR
13-
"Error, in source builds are not supported. If you really want an in source build (and know what you are doing) you may set the advanced ALLOW_IN_SOURCE_BUILDS variable to ON. Otherwise create a build directory not matching the source directory, '${CMAKE_SOURCE_DIR}'." )
14-
endif ( ALLOW_IN_SOURCE_BUILDS )
13+
"Error, in source builds are not supported. If you really want an in source build (and know what you are doing) you may set the advanced ENABLE_IN_SOURCE_BUILDS variable to ON. Otherwise create a build directory not matching the source directory, '${CMAKE_SOURCE_DIR}'." )
14+
endif ( ENABLE_IN_SOURCE_BUILDS )
1515
endif ( "${FULL_BUILD_DIR}" STREQUAL "${FULL_SOURCE_DIR}" )

cmake/pickFortranCompilerFlags.cmake

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
if ( NOT Fortran_FLAGS_INIT )
22
set ( Fortran_FLAGS_INIT TRUE )
3-
set ( CALL_STACK_BACK_TRACE TRUE CACHE BOOL
3+
set ( ENABLE_BACK_TRACE TRUE CACHE BOOL
44
"Enable backtraces on unexpected runtime errors? (Recommended)" )
55
set ( ENABLE_COMPILE_TIME_WARNINGS TRUE CACHE BOOL
66
"Enable diagnostic warnings at compile time? (Recommended)" )
@@ -9,9 +9,9 @@ if ( NOT Fortran_FLAGS_INIT )
99
mark_as_advanced ( ENABLE_RUNTIME_CHECKS )
1010

1111
if ( "${CMAKE_Fortran_COMPILER_ID}" MATCHES "Intel" )
12-
if ( CALL_STACK_BACK_TRACE )
12+
if ( ENABLE_BACK_TRACE )
1313
add_compile_options ( -traceback )
14-
endif ( CALL_STACK_BACK_TRACE )
14+
endif ( ENABLE_BACK_TRACE )
1515
if ( ENABLE_COMPILE_TIME_WARNINGS )
1616
# The following warning might be triggered by ifort unless explicitly silenced:
1717
# warning #7601: F2008 standard does not allow an internal procedure to be an actual argument procedure
@@ -23,9 +23,9 @@ if ( NOT Fortran_FLAGS_INIT )
2323
add_compile_options ( -check all )
2424
endif ( ENABLE_RUNTIME_CHECKS )
2525
elseif ( "{CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU" )
26-
if ( CALL_STACK_BACK_TRACE )
26+
if ( ENABLE_BACK_TRACE )
2727
add_compile_options ( -fbacktrace )
28-
endif ( CALL_STACK_BACK_TRACE )
28+
endif ( ENABLE_BACK_TRACE )
2929
if ( ENABLE_COMPILETIME_CHECKS )
3030
add_compile_options ( -Wall -Wextra -Wno-maybe-uninitialized -pedantic -std=f2008 )
3131
endif ( ENABLE_COMPILETIME_CHECKS )

0 commit comments

Comments
 (0)