Skip to content

Commit a7847c5

Browse files
committed
Improved build logic to ensure consisten Fortran compilers
- README.md updated and reflowed - jsonfortran-${CMAKE_Fortran_COMPILER_ID} is now passed to `find_package()` by projects wishing to import jsonfortran - libraries and mod files installed under fortran/${CMAKE_Fortran_COMPILER_ID} to enable parallel installation of packages built by different compilers the package config logic ensures that the correct compiler is used
1 parent dd9077a commit a7847c5

File tree

5 files changed

+107
-33
lines changed

5 files changed

+107
-33
lines changed

CMakeLists.txt

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ cmake_minimum_required ( VERSION 2.8 FATAL_ERROR )
1616
enable_language ( Fortran )
1717
#include ( cmake/CompilerCompatibilityCheck.cmake )
1818

19+
# Check for in-source builds and error out if found
20+
# Provides an advanced option to allow in source builds
21+
include ( "cmake/checkOutOfSource.cmake" )
22+
1923
#---------------------
2024
# Declare project name
2125
#---------------------
@@ -28,7 +32,7 @@ project ( jsonfortran NONE )
2832
set ( VERSION_MAJOR 1 )
2933
set ( VERSION_MINOR 0 )
3034
set ( VERSION_PATCH 0 )
31-
set ( version ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} )
35+
set ( VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" )
3236

3337
#-------------------------------------
3438
# Collect source files for the library
@@ -56,14 +60,15 @@ set_target_properties ( ${LIB_NAME}-static
5660
PROPERTIES
5761
OUTPUT_NAME ${LIB_NAME}
5862
PREFIX lib
59-
VERSION ${version} )
63+
VERSION ${VERSION} )
6064
set_target_properties ( ${LIB_NAME}
6165
PROPERTIES
6266
SOVERSION ${VERSION_MAJOR}.${VERSION_MINOR} )
6367

6468
#-------------------------------------
6569
# Define where our files get installed
6670
#-------------------------------------
71+
6772
if ( ${CMAKE_SYSTEM_NAME} MATCHES "Linux" )
6873
include ( GNU_Install_Dirs ) # Standard CMake module
6974
elseif ( UNIX ) #Apple, BSD, solaris, other *NIX? Framework on Apple instead?
@@ -72,48 +77,68 @@ elseif ( UNIX ) #Apple, BSD, solaris, other *NIX? Framework on Apple instead?
7277
set ( CMAKE_INSTALL_DATAROOTDIR share )
7378
endif ( ${CMAKE_SYSTEM_NAME} MATCHES "Linux" )
7479

80+
# Set the package name to be specific to the compiler used, so that
81+
# versions compiled with different compilers can be installed in parallel
82+
string ( TOLOWER ${CMAKE_PROJECT_NAME}-${CMAKE_Fortran_COMPILER_ID} PACKAGE_NAME )
83+
7584
install ( TARGETS ${LIB_NAME} ${LIB_NAME}-static
76-
EXPORT ${CMAKE_PROJECT_NAME}-targets
77-
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
78-
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) # We may need something different for windows
85+
EXPORT ${PACKAGE_NAME}-targets
86+
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/fortran/${CMAKE_Fortran_COMPILER_ID}-compiler"
87+
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}/fortran/${CMAKE_Fortran_COMPILER_ID}-compiler" )
7988

80-
set ( INSTALL_MOD_DIR "${CMAKE_INSTALL_INCLUDEDIR}/fortran/${CMAKE_Fortran_COMPILER_ID}" )
89+
set ( INSTALL_MOD_DIR "${CMAKE_INSTALL_INCLUDEDIR}/fortran/${CMAKE_Fortran_COMPILER_ID}-compiler" )
8190
install ( DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY}/ DESTINATION "${INSTALL_MOD_DIR}" )
8291

8392
#-----------------------------------------------------
8493
# Publicize installed location to other CMake projects
8594
#-----------------------------------------------------
8695
set ( EXPORT_INSTALL_DIR
87-
${CMAKE_INSTALL_DATAROOTDIR}/cmake/${CMAKE_PROJECT_NAME}-${version} )
88-
install ( EXPORT ${CMAKE_PROJECT_NAME}-targets DESTINATION ${EXPORT_INSTALL_DIR} )
96+
${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PACKAGE_NAME}-${VERSION} )
97+
install ( EXPORT ${PACKAGE_NAME}-targets DESTINATION ${EXPORT_INSTALL_DIR} )
8998

9099
include ( CMakePackageConfigHelpers ) # Standard CMake module
91-
write_basic_package_version_file( ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-config-version.cmake
92-
VERSION ${version}
100+
write_basic_package_version_file( ${CMAKE_BINARY_DIR}/${PACKAGE_NAME}-config-version.cmake
101+
VERSION ${VERSION}
93102
COMPATIBILITY SameMajorVersion )
94103

104+
# Put common compiler compatibility check in a variable to be written out, rather than
105+
# duplicating it across the build and install package-config files
106+
set ( COMPILER_CONSISTENCY_CHECK
107+
"# Check that the correct compiler is in use. Mod files and object files/archives
108+
# are NOT compatible across different Fortran compilers when modules are present
109+
set ( ${PACKAGE_NAME}_Fortran_COMPILER_ID ${CMAKE_Fortran_COMPILER_ID} )
110+
set ( ${PACKAGE_NAME}_COMPATIBLE_COMPILER TRUE )
111+
if ( NOT (\"${CMAKE_Fortran_COMPILER_ID}\" MATCHES \"\${CMAKE_Fortran_COMPILER_ID}\") )
112+
message ( SEND_ERROR \"Incompatible Fortran compilers detected! ${PACKAGE_NAME} was compiled with the ${CMAKE_Fortran_COMPILER_ID} Fortran compiler, but the current project is trying to use the \${CMAKE_Fortran_COMPILER_ID} Fortran compiler! In general, Fortran modules and libraries can only link against other projects built using the same compiler.\" )
113+
set ( ${PACKAGE_NAME}_COMPATIBLE_COMPILER FALSE )
114+
endif ( NOT (\"${CMAKE_Fortran_COMPILER_ID}\" MATCHES \"\${CMAKE_Fortran_COMPILER_ID}\") )" )
115+
95116
# install package config file
96117
configure_package_config_file (
97118
${CMAKE_SOURCE_DIR}/cmake/pkg/${CMAKE_PROJECT_NAME}-config.cmake.in
98-
${CMAKE_BINARY_DIR}/pkg/${CMAKE_PROJECT_NAME}-config.cmake
119+
${CMAKE_BINARY_DIR}/pkg/${PACKAGE_NAME}-config.cmake
99120
INSTALL_DESTINATION ${EXPORT_INSTALL_DIR}
100121
PATH_VARS EXPORT_INSTALL_DIR INSTALL_MOD_DIR )
101122

102123
# Install the config and version files so that we can find this project with others
103124
install ( FILES
104-
${CMAKE_BINARY_DIR}/pkg/${CMAKE_PROJECT_NAME}-config.cmake
105-
${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-config-version.cmake
125+
${CMAKE_BINARY_DIR}/pkg/${PACKAGE_NAME}-config.cmake
126+
${CMAKE_BINARY_DIR}/${PACKAGE_NAME}-config-version.cmake
106127
DESTINATION ${EXPORT_INSTALL_DIR} )
107128

108129
#----------------------------------------------
109130
# Make build tree targets accessible for import
110131
#----------------------------------------------
111-
export ( TARGETS ${LIB_NAME} ${LIB_NAME}-static FILE ${CMAKE_PROJECT_NAME}-targets.cmake )
132+
export ( TARGETS ${LIB_NAME} ${LIB_NAME}-static FILE ${PACKAGE_NAME}-targets.cmake )
112133

113134
# build tree package config file, NOT installed
114135
configure_file (
115136
${CMAKE_SOURCE_DIR}/cmake/${CMAKE_PROJECT_NAME}-config.cmake.in
116-
${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-config.cmake
137+
${CMAKE_BINARY_DIR}/${PACKAGE_NAME}-config.cmake
117138
@ONLY )
118139

119-
export ( PACKAGE jsonfortran )
140+
set ( ADD_BUILD_TREE_TO_REGISTRY CACHE BOOL TRUE
141+
"Add the ${PACKAGE_NAME} build tree to the CMake package registry?" )
142+
if ( ADD_BUILD_TREE_TO_REGISTRY )
143+
export ( PACKAGE ${PACKAGE_NAME} )
144+
endif ( ADD_BUILD_TREE_TO_REGISTRY )

README.md

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,39 @@ A Fortran 2003/2008 JSON API
66
Brief Description
77
---------------
88

9-
A mostly-complete API for reading and writing JSON files, written in modern Fortran. The code requires a Fortran compiler that supports various Fortran 2003 and Fortran 2008 features such as: allocatable strings, associate, newunit, generic, class, and abstract interface. I am using the Intel Fortran compiler 13.1.0 on Linux (the Mac and PC versions should also work fine). It also currently compiles under recent experimental 4.9 release of the gnu gfortran compiler. The source code is a single Fortran module file (json_module.f90).
9+
A mostly-complete API for reading and writing JSON files, written in
10+
modern Fortran. The code requires a Fortran compiler that supports
11+
various Fortran 2003 and Fortran 2008 features such as: allocatable
12+
strings, associate, newunit, generic, class, and abstract interface.
13+
I am using the Intel Fortran compiler 13.1.0 on Linux (the Mac and PC
14+
versions should also work fine). It also currently compiles under
15+
recent experimental 4.9 release of the gnu gfortran compiler. The
16+
source code is a single Fortran module file (json_module.f90).
1017

1118
Building the Library
1219
--------------------
13-
Currently two way are provided to build the jsonfortran library (libjsonfortran). A build script, build.sh is provided in the project root directory. Additionally, a [CMake](http://www.cmake.org) build system is provided. This build system has been tested on Mac and Linux using the Intel Fortran Compiler. It has not been tested on Windows. This CMake based build provides an install target, and exports from both the install location and the build location so that building and using json-fortran in another CMake based project is trivial. To get started with the CMake based build, set the environment variable `FC` to point to your Fortran compiler, and create a build directory. Then `(cmake-gui|ccmake|cmake) /path/to/json-fortran` to configure, `make` to build and `make install` to optionally install. As long as the project is built with CMake other CMake projects can find it and link against it:
20+
21+
Currently two ways are provided to build the jsonfortran library
22+
(libjsonfortran). A build script, build.sh is provided in the project
23+
root directory. Additionally, a [CMake](http://www.cmake.org) build
24+
system is provided. This build system has been tested on Mac and Linux
25+
using the Intel Fortran Compiler. It has not been tested on
26+
Windows. This CMake based build provides an install target, and
27+
exports from both the install location and the build location so that
28+
building and using json-fortran in another CMake based project is
29+
trivial. To get started with the CMake based build, set the
30+
environment variable `FC` to point to your Fortran compiler, and
31+
create a build directory. Then `(cmake-gui|ccmake|cmake)
32+
/path/to/json-fortran` to configure, `make` to build and `make
33+
install` to optionally install. As long as the project is built with
34+
CMake other CMake projects can find it and link against it:
1435

1536
```CMake
1637
cmake_minimum_required ( VERSION 2.8 FATAL_ERROR )
1738
enable_language ( Fortran )
1839
project ( jf_test NONE )
1940
20-
find_package ( jsonfortran 1.0.0 REQUIRED )
41+
find_package ( jsonfortran-${CMAKE_Fortran_COMPILER_ID} 1.0.0 REQUIRED )
2142
2243
add_executable ( json_example src/json_example.f90 )
2344
target_include_directories ( json_example BEFORE PUBLIC ${jsonfortran_INCLUDE_DIRS} )
@@ -27,9 +48,11 @@ target_link_libraries ( json_example jsonfortran-static )
2748
Reading a JSON file
2849
---------------
2950

30-
Reading a JSON file and getting data from it is fairly straightforward. Here is an example. See the json_example.f90 file for more examples.
31-
```fortran
32-
program example1
51+
Reading a JSON file and getting data from it is fairly
52+
straightforward. Here is an example. See the json_example.f90 file
53+
for more examples.
54+
55+
```fortran program example1
3356
3457
use json_module
3558
@@ -61,9 +84,10 @@ Reading a JSON file and getting data from it is fairly straightforward. Here is
6184
Writing a JSON file
6285
---------------
6386

64-
Writing a json file is slightly more complicated and involves the use of pointers. See the json_example.f90 file for more examples.
65-
```fortran
66-
program example2
87+
Writing a json file is slightly more complicated and involves the use
88+
of pointers. See the json_example.f90 file for more examples.
89+
90+
```fortran program example2
6791
6892
use json_module
6993
@@ -102,13 +126,18 @@ Writing a json file is slightly more complicated and involves the use of pointer
102126
!cleanup:
103127
call json_destroy(p)
104128
105-
end program example2
129+
end program example2
106130
```
131+
107132
Other Comments
108133
---------------
109134

110-
This code is a fork and extensive upgrade of the FSON code that can be found at: <https://github.com/josephalevin/fson>. It includes many features that the original code did not have, and fixes many of that code's bugs.
135+
This code is a fork and extensive upgrade of the FSON code that can be
136+
found at: <https://github.com/josephalevin/fson>. It includes many
137+
features that the original code did not have, and fixes many of that
138+
code's bugs.
111139

112140
More About JSON
113141
------------
114-
For more information about JSON, see: <http://www.json.org/>
142+
143+
For more information about JSON, see: [json.org](http://www.json.org/)

cmake/checkOutOfSource.cmake

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
option ( ALLOW_IN_SOURCE_BUILDS
2+
"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."
3+
OFF )
4+
mark_as_advanced ( ALLOW_IN_SOURCE_BUILDS )
5+
get_filename_component ( FULL_BUILD_DIR "${CMAKE_BINARY_DIR}" REALPATH )
6+
get_filename_component ( FULL_SOURCE_DIR "${CMAKE_SOURCE_DIR}" REALPATH )
7+
if ( "${FULL_BUILD_DIR}" STREQUAL "${FULL_SOURCE_DIR}" )
8+
if ( ALLOW_IN_SOURCE_BUILDS )
9+
message ( WARNING
10+
"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 )
12+
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 )
15+
endif ( "${FULL_BUILD_DIR}" STREQUAL "${FULL_SOURCE_DIR}" )

cmake/jsonfortran-config.cmake.in

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
# No need to use CMakePackageConfigHelpers since we know all the paths with
55
# certainty in the build tree.
66

7+
set ( @CMAKE_PROJECT_NAME@_VERSION @VERSION@ )
8+
9+
@COMPILER_CONSISTENCY_CHECK@
10+
711
# Make targets available to be built
8-
include ( "@CMAKE_BINARY_DIR@/@CMAKE_PROJECT_NAME@-targets.cmake" )
12+
include ( "@CMAKE_BINARY_DIR@/@PACKAGE_NAME@-targets.cmake" )
913

1014
# Tell the compiler where to find the mod files
1115
set ( @CMAKE_PROJECT_NAME@_INCLUDE_DIRS "@CMAKE_Fortran_MODULE_DIRECTORY@" )

cmake/pkg/jsonfortran-config.cmake.in

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
# Allow other CMake projects to find this package if it is installed
33
# Requires the use of the standard CMake module CMakePackageConfigHelpers
44

5-
set ( @CMAKE_PROJECT_NAME@_VERSION @version@ )
5+
set ( @CMAKE_PROJECT_NAME@_VERSION @VERSION@ )
66

7-
@PACKAGE_INIT@
7+
@COMPILER_CONSISTENCY_CHECK@
88

9+
@PACKAGE_INIT@
910

1011
# Provide the targets
11-
set_and_check ( @CMAKE_PROJECT_NAME@_CONFIG_INSTALL_DIR "@PACKAGE_EXPORT_INSTALL_DIR@" )
12-
include ( "${@CMAKE_PROJECT_NAME@_CONFIG_INSTALL_DIR}/@CMAKE_PROJECT_NAME@-targets.cmake" )
12+
set_and_check ( @PACKAGE_NAME@_CONFIG_INSTALL_DIR "@PACKAGE_EXPORT_INSTALL_DIR@" )
13+
include ( "${@PACKAGE_NAME@_CONFIG_INSTALL_DIR}/@PACKAGE_NAME@-targets.cmake" )
1314

1415
# Make the module files available via include
1516
set_and_check ( @CMAKE_PROJECT_NAME@_INCLUDE_DIRS "@PACKAGE_INSTALL_MOD_DIR@" )

0 commit comments

Comments
 (0)