Skip to content

Commit d8d4ef8

Browse files
committed
fix: install library and CMake package files, not just headers
1 parent 0534152 commit d8d4ef8

5 files changed

Lines changed: 146 additions & 53 deletions

File tree

CMakeLists.txt

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ if(APPLE AND NOT DEFINED CMAKE_OSX_DEPLOYMENT_TARGET)
2323
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Minimum OS X deployment version")
2424
endif()
2525

26-
if(WIN32)
27-
add_compile_options("/bigobj")
28-
endif()
29-
3026
###############################################################################
3127
# Project definition.
3228

@@ -43,6 +39,15 @@ set(CMAKE_MODULE_PATH
4339
${PROJECT_SOURCE_DIR}/cmake/modules
4440
)
4541

42+
# Some translation units exceed the default COFF section limit. This has to come
43+
# after project(), which is what defines WIN32 and the compiler id.
44+
if(MSVC)
45+
add_compile_options("/bigobj")
46+
elseif(WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "GNU")
47+
# MinGW spells the same thing differently, and rejects /bigobj outright.
48+
add_compile_options("-Wa,-mbig-obj")
49+
endif()
50+
4651
###############################################################################
4752
# Forbid in-source build.
4853

@@ -78,6 +83,10 @@ endif()
7883
# Setting to C++ standard to C++17
7984
set(CMAKE_CXX_STANDARD 17)
8085

86+
# Standard bin/lib/include/share layout, needed by the install rules below and
87+
# by the INSTALL_INTERFACE of the casbin target.
88+
include(GNUInstallDirs)
89+
8190
###############################################################################
8291
# Install external dependencies
8392
# Some required targets may be created by third-party CMake configs, which
@@ -170,22 +179,66 @@ endif()
170179
# Install casbin
171180

172181
if(CASBIN_INSTALL)
173-
message(CHECK_START "[casbin]: Installing casbin ...")
174-
export(
182+
message(CHECK_START "[casbin]: Configuring the casbin installation ...")
183+
184+
include(CMakePackageConfigHelpers)
185+
186+
set(CASBIN_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/casbin"
187+
CACHE STRING "Path to the installed casbin CMake package files")
188+
189+
# Installing headers
190+
install(
191+
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/casbin
192+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
193+
)
194+
195+
# Installing the library itself. Without this the installed tree only ever
196+
# contained headers, so downstream projects had nothing to link against.
197+
install(
175198
TARGETS casbin
199+
EXPORT casbinTargets
200+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
201+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
202+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
203+
)
204+
205+
# Installing the CMake package files so that find_package(casbin) works
206+
# against the install prefix (and hence for package managers such as vcpkg)
207+
# instead of only against the CMake User Package Registry.
208+
install(
209+
EXPORT casbinTargets
210+
FILE casbinTargets.cmake
176211
NAMESPACE casbin::
177-
FILE casbinConfig.cmake
212+
DESTINATION ${CASBIN_INSTALL_CMAKEDIR}
213+
)
214+
215+
configure_package_config_file(
216+
${CMAKE_CURRENT_SOURCE_DIR}/cmake/casbinConfig.cmake.in
217+
${CMAKE_CURRENT_BINARY_DIR}/casbinConfig.cmake
218+
INSTALL_DESTINATION ${CASBIN_INSTALL_CMAKEDIR}
219+
)
220+
221+
write_basic_package_version_file(
222+
${CMAKE_CURRENT_BINARY_DIR}/casbinConfigVersion.cmake
223+
VERSION ${PROJECT_VERSION}
224+
COMPATIBILITY SameMajorVersion
178225
)
179226

180-
# Installing headers
181227
install(
182-
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/casbin
183-
DESTINATION include
228+
FILES
229+
${CMAKE_CURRENT_BINARY_DIR}/casbinConfig.cmake
230+
${CMAKE_CURRENT_BINARY_DIR}/casbinConfigVersion.cmake
231+
DESTINATION ${CASBIN_INSTALL_CMAKEDIR}
184232
)
185233

186-
set(CMAKE_EXPORT_PACKAGE_REGISTRY ON)
187-
export(PACKAGE casbin)
234+
# Also export the targets for the build tree, so that a project using
235+
# FetchContent/add_subdirectory can consume casbin:: without installing.
236+
export(
237+
EXPORT casbinTargets
238+
NAMESPACE casbin::
239+
FILE ${CMAKE_CURRENT_BINARY_DIR}/casbinTargets.cmake
240+
)
188241

189-
message(CHECK_PASS " The targets can now be imported with find_package(casbin)")
190-
message(STATUS "[casbin]: Build the \"install\" target and add \"${CMAKE_INSTALL_PREFIX}/include\" to you PATH for casbin to work")
242+
message(CHECK_PASS " done")
243+
message(STATUS "[casbin]: Build the \"install\" target, then use find_package(casbin) and link against casbin::casbin")
191244
endif()

README.md

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,11 @@ your may link your own targets against casbin's likewise:
157157
```cmake
158158
add_executable(myexec main.cpp)
159159
160-
target_link_libraries(myexec PRIVATE casbin)
161-
162-
set(myexec_INCLUDE_DIR ${casbin_SOURCE_DIR}/include)
163-
target_include_directories(myexec PRIVATE ${myexec_INCLUDE_DIR})
160+
target_link_libraries(myexec PRIVATE casbin::casbin)
164161
```
165162

166-
Do remember to include `casbin_SOURCE_DIR/include` directory wherever casbin's functions are utilised.
163+
The `casbin::casbin` target carries its own include directories, so you don't need to
164+
add `casbin_SOURCE_DIR/include` yourself.
167165

168166
### With local installation
169167

@@ -183,13 +181,8 @@ You may integrate casbin into your CMake project through `find_package`.
183181
cmake ..
184182
```
185183

186-
**Note:** Look up for the logs of this step. And add the path indicated by the log into your PATH/project include directory.
187-
The log message you're looking for should be something like this:
188-
```bash
189-
[casbin]: Installing casbin ...
190-
[casbin]: Installing casbin ... - The targets can now be imported with find_package(casbin)
191-
[casbin]: Build the "install" target and add "/usr/local/include" to you PATH for casbin to work
192-
```
184+
Use `-DCMAKE_INSTALL_PREFIX=<path>` if you don't want to install into the default
185+
location (`C:/Program Files/casbin` on Windows, `/usr/local` on Linux/macOS).
193186
194187
3. After the project is configured successfully, build it:
195188
```bash
@@ -209,12 +202,13 @@ You may integrate casbin into your CMake project through `find_package`.
209202
```
210203
This will import all the targets exported by casbin to your project
211204

212-
6. Link against casbin (Refer to Step 2's **Note** to get the value of `MY_INCLUDE_DIR` for your system):
205+
6. Link against casbin:
213206
```cmake
214-
set(MY_INCLUDE_DIR "/usr/local/include")
215-
target_include_directories(MyTargetName PRIVATE ${MY_INCLUDE_DIR})
216207
target_link_libraries(MyTargetName PRIVATE casbin::casbin)
217208
```
209+
The include directories come with the target, so there is no need to set them by hand.
210+
If you installed into a non-default prefix, point CMake at it with
211+
`-DCMAKE_PREFIX_PATH=<path>`.
218212

219213
## Installation and Set-Up
220214

@@ -249,13 +243,14 @@ You may integrate casbin into your CMake project through `find_package`.
249243
cmake --build . --target install
250244
```
251245

252-
- For **Windows**, this will install `casbin.lib` to `<custom-path>/casbin-cpp/build/casbin`
253-
and the headers to `C:/Program Files/casbin/include`.
254-
- For Unix based OS i.e. **Linux and macOS**, this will install `casbin.a` to `<custom-path>/casbin-cpp/build/casbin`
255-
and the headers to `usr/local/include`.
246+
This installs everything under `CMAKE_INSTALL_PREFIX` (`C:/Program Files/casbin` on Windows,
247+
`/usr/local` on Linux/macOS by default):
248+
249+
- the library into `lib/` (`casbin.lib` on Windows, `libcasbin.a` on Linux/macOS),
250+
- the headers into `include/casbin/`,
251+
- the CMake package files into `lib/cmake/casbin/`, so that `find_package(casbin)` finds it.
256252

257-
You can add the respective include and lib paths
258-
to the PATH environment variable to use casbin.
253+
Pass `-DCMAKE_INSTALL_PREFIX=<path>` at configure time to install somewhere else.
259254

260255
5. (OPTIONAL) To run the tests, issue the following command from `/build`:
261256

casbin/CMakeLists.txt

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,29 @@ set(CASBIN_SOURCE_FILES
7474
set(CMAKE_CXX_STANDARD 17)
7575

7676
add_library(casbin STATIC ${CASBIN_SOURCE_FILES})
77+
# So that add_subdirectory()/FetchContent consumers can use the same name as
78+
# find_package() consumers.
79+
add_library(casbin::casbin ALIAS casbin)
7780

7881
target_precompile_headers(casbin PRIVATE ${CASBIN_INCLUDE_DIR}/casbin/pch.h)
79-
target_include_directories(casbin PRIVATE ${CASBIN_INCLUDE_DIR})
82+
83+
# Consumers must see the headers too, both from the build tree and from an
84+
# installed prefix, otherwise find_package(casbin) hands out a target that
85+
# cannot be compiled against.
86+
target_include_directories(casbin
87+
PUBLIC
88+
$<BUILD_INTERFACE:${CASBIN_INCLUDE_DIR}>
89+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
90+
)
8091
target_link_libraries(casbin PUBLIC nlohmann_json::nlohmann_json)
8192

82-
set_target_properties(casbin PROPERTIES
83-
PREFIX ""
93+
# Keep the platform default naming (libcasbin.a / casbin.lib) so that the
94+
# installed library looks like every other system library and can be picked up
95+
# with a plain -lcasbin.
96+
set_target_properties(casbin PROPERTIES
8497
VERSION ${PROJECT_VERSION}
8598
)
8699

87-
if(WIN32 OR MSVC)
88-
set_target_properties(casbin PROPERTIES SUFFIX ".lib")
89-
elseif(UNIX)
90-
set_target_properties(casbin PROPERTIES
91-
SUFFIX ".a"
92-
POSITION_INDEPENDENT_CODE ON
93-
)
100+
if(UNIX)
101+
set_target_properties(casbin PROPERTIES POSITION_INDEPENDENT_CODE ON)
94102
endif()

cmake/casbinConfig.cmake.in

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright 2023 The casbin Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
@PACKAGE_INIT@
16+
17+
include(CMakeFindDependencyMacro)
18+
19+
# casbin::casbin links nlohmann_json publicly, so consumers need it as well.
20+
find_dependency(nlohmann_json 3.10.1)
21+
22+
include("${CMAKE_CURRENT_LIST_DIR}/casbinTargets.cmake")
23+
24+
check_required_components(casbin)

cmake/modules/Findjson.cmake

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,26 @@
1414
# limitations under the License.
1515
include(FetchContent)
1616

17-
set(JSON_Install ON)
17+
# Prefer a nlohmann_json that is already available on the system (this is what
18+
# package managers such as vcpkg or Conan provide); only download a copy when
19+
# there is none, so that packaged builds don't vendor their own.
20+
option(CASBIN_FETCH_JSON "Always download nlohmann_json instead of using the system one" OFF)
1821

19-
FetchContent_Declare(
20-
json
21-
GIT_REPOSITORY https://github.com/nlohmann/json.git
22-
GIT_TAG v3.11.2
23-
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
24-
)
22+
if(NOT CASBIN_FETCH_JSON)
23+
find_package(nlohmann_json 3.10.1 CONFIG QUIET)
24+
endif()
2525

26-
FetchContent_MakeAvailable(json)
26+
if(NOT nlohmann_json_FOUND)
27+
set(JSON_Install ON)
28+
29+
FetchContent_Declare(
30+
json
31+
GIT_REPOSITORY https://github.com/nlohmann/json.git
32+
GIT_TAG v3.11.2
33+
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
34+
)
35+
36+
FetchContent_MakeAvailable(json)
37+
endif()
38+
39+
set(json_FOUND TRUE)

0 commit comments

Comments
 (0)