Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposition of a different packaging for this project #3

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ cmake-build-debug
cmake-build-debug-coverage
build
scratch
.vscode
191 changes: 122 additions & 69 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,89 +1,142 @@
cmake_minimum_required(VERSION 3.1)
cmake_minimum_required(VERSION 3.24)

project(
"http-link-header-cpp"
VERSION 0.9.0
DESCRIPTION
"A header only c++ library that can parse HTTP Link: header fields as described in RFC8288."
HOMEPAGE_URL "https://github.com/dcdpr/http-link-header-cpp"
LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)
"http-link-header-cpp"
VERSION 0.9.0
DESCRIPTION
"A header only c++ library that can parse HTTP Link: header fields as described in RFC8288."
HOMEPAGE_URL "https://github.com/dcdpr/http-link-header-cpp"
LANGUAGES CXX)

option(HLH_BUILD_TESTING "Enable unit tests" ON)
option(USE_CONAN "If Conan is installed, use Conan to pull the project dependencies" OFF)

###############
# Conan support
###############

find_program (CONAN_BIN conan)
if(CONAN_BIN AND USE_CONAN)
message (STATUS "Found conan C++ package manager: ${CONAN_BIN}")
find_file (CONANFILE NAMES "conanfile.txt" HINTS "${CMAKE_SOURCE_DIR}")
if (CONANFILE)
message (STATUS "Found ${CONANFILE}")
if (NOT EXISTS "${CMAKE_BINARY_DIR}/conanbuildinfo.cmake")
message(STATUS "Trying to execute 'conan install'")
get_filename_component(CONANFILE_DIR ${CONANFILE} DIRECTORY)
execute_process(COMMAND conan install ${CONANFILE_DIR} --build=missing)
endif()
endif()

if (EXISTS "${CMAKE_BINARY_DIR}/conanbuildinfo.cmake")
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
message(STATUS "conan_basic_setup()")
conan_basic_setup(TARGETS)
else()
message(WARNING "Please run 'conan install' if you plan to use conan")
endif()
endif()

##########################################
# Local CMake scripts and finders (if any)
##########################################

if (EXISTS "${CMAKE_SOURCE_DIR}/cmake/Modules/")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
endif()

###############################
# Check compiler's capabilities
###############################

include (CheckCCompilerFlag)
include (CheckCXXCompilerFlag)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set (CMAKE_COMPILER_IS_CLANG true)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set (CMAKE_COMPILER_IS_MSVC true)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG)
find_program (LINKER_BIN gold)
if(LINKER_BIN)
set(LINKER_BIN "gold")
else()
find_program (LINKER_BIN ld.gold)
if(LINKER_BIN)
set(LINKER_BIN "ld.gold")
else()
set(LINKER_BIN "ld")
endif()
endif()

if (CMAKE_COMPILER_IS_GNUCXX)
add_compile_options(-fdiagnostics-color=always)
elseif (CMAKE_COMPILER_IS_CLANG)
add_compile_options(-fcolor-diagnostics)
endif()

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
#set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=address")

CHECK_CXX_COMPILER_FLAG("-fuse-ld=${LINKER_BIN}" USE_LINKER_LD_GOLD)
if(USE_LINKER_LD_GOLD)
set (CMAKE_SHARED_LINKER_FLAGS "-fuse-ld=${LINKER_BIN} ${CMAKE_SHARED_LINKER_FLAGS}")
endif()
endif()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(uriparser 0.9.5 CONFIG REQUIRED char wchar_t)
if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
set(CMAKE_MACOSX_RPATH OFF)
endif()

add_library(${PROJECT_NAME} INTERFACE)
# add alias so the project can be embedded by others and used with add_subdirectory()
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
set (CMAKE_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include")
set (CMAKE_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/lib")
set (CMAKE_INSTALL_BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
message(STATUS "CMAKE_INSTALL_INCLUDEDIR: ${CMAKE_INSTALL_INCLUDEDIR}")
message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}")
message(STATUS "CMAKE_INSTALL_BINDIR: ${CMAKE_INSTALL_BINDIR}")

include(GNUInstallDirs)
include(CTest)

# determine if we are building http-link-header-cpp itself, or if we are embedded in another project
if(${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME})
set(IS_TOPLEVEL_PROJECT TRUE)
else()
set(IS_TOPLEVEL_PROJECT FALSE)
endif()
###############################
# Library
###############################

# only enable installing if we aren't embedded in another project
option(HLH_INSTALL_LIBRARY
"Enable installing of http-link-header-cpp library into default locations"
${IS_TOPLEVEL_PROJECT})
find_package(uriparser 0.9.7 CONFIG REQUIRED char wchar_t)

# only enable tests if we aren't embedded in another project
option(HLH_BUILD_TESTING
"Enable building and running http-link-header-cpp tests"
${IS_TOPLEVEL_PROJECT})
add_library(${PROJECT_NAME} INTERFACE)

target_include_directories(
${PROJECT_NAME}
target_include_directories(${PROJECT_NAME}
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_11)
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17)

target_link_libraries(${PROJECT_NAME} INTERFACE uriparser::uriparser)

if(BUILD_TESTING AND HLH_BUILD_TESTING)
add_subdirectory(test)
endif()
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/http-link-header" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

if(HLH_INSTALL_LIBRARY)
# locations are provided by GNUInstallDirs
install(
TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}_Targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${PROJECT_NAME}ConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)

configure_package_config_file(
"${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)

install(
EXPORT ${PROJECT_NAME}_Targets
FILE ${PROJECT_NAME}Targets.cmake
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)

install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake)

install(FILES ${PROJECT_SOURCE_DIR}/include/http-link-header.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
endif()

###############################
# Testing
###############################

if(HLH_BUILD_TESTING)
enable_testing()
add_subdirectory(test)
else()
message(STATUS "Skipping unit tests")
endif()
107 changes: 48 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,82 +53,71 @@ such links in HTTP headers with the "Link:" header field.
std::cout << links[1].linkTarget << std::endl; // https://example.org/a/other
```

## Building

`http-link-header-cpp` is a header-only C++11 library. Building can be done with cmake >= 3.1 and has been tested with g++ and clang compilers.

`http-link-header-cpp` uses a pretty standard cmake build system. After cloning the repository, execute the following:

```shell
cd http-link-header-cpp
mkdir build
cd build
cmake ..
cmake --build . --config Release
```

You can also run all the tests:

```shell
make test
```

## Dependencies

`http-link-header-cpp` has a dependency on [uriparser](https://github.com/uriparser/uriparser/)
which it uses when resolving URI references. Any project using `http-link-header-cpp` should also be able to find a copy of
uriparser. uriparser should either be installed locally or included within the the project's code.
### Build dependencies / runtime dependencies
- [uriparser](https://github.com/uriparser/uriparser/): used when resolving URI references.

## Installing
### Test dependencies
- [doctest](https://github.com/doctest/doctest): used in the unit tests.

`http-link-header-cpp` will install its header file, `http-link-header.h`, and a few cmake helper files that can be used by other
projects to find and use `http-link-header-cpp`.
## Development pre-requisites

The default installation locations for `http-link-header-cpp` are `/usr/local/include` and `/usr/local/share`.
1. Install a toolchain. `http-link-header-cpp` is a header-only C++11 library. You will need a recent GCC or Clang compiler supporting fully C++17 at least.
2. Install CMake.
3. Install Python.
4. Install conan: `python3 -m pip install -U conan` (more details at [docs.conan.io](https://docs.conan.io/en/latest/index.html))
- run `conan` once to initialize conan home (`~/.conan`)
- create a conan profile for the default system compiler

To install using cmake after building and testing, execute the following:
## Development workflow

```shell
cmake --build . --config Release --target install
After cloning the repository, create a build directory at the root of the package.
```txt
mkdir build-dir && cd build-dir
```

You should see output similar to:

```shell
-- Installing: /usr/local/share/http-link-header-cpp/cmake/http-link-headerTargets.cmake
-- Installing: /usr/local/share/http-link-header-cpp/cmake/http-link-headerConfig.cmake
-- Installing: /usr/local/share/http-link-header-cpp/cmake/http-link-headerConfigVersion.cmake
-- Installing: /usr/local/include/http-link-header.h
Pull the dependencies with Conan.
```txt
conan install --build=missing ..
```

If you want the files to be installed somewhere different, you can set the installation prefix when running the initial cmake command. For example:

Generate the build scripts with `cmake`.
```shell
cmake -DCMAKE_INSTALL_PREFIX:PATH=/tmp/http-link-header-cpp-install ..
cmake --build . --config Release --target install
cmake -DUSE_CONAN=ON \
-GNinja \
-DCMAKE_PREFIX_PATH=$(pwd) \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$(pwd)/sysroot \
.. # the directory containing the conanfile.txt
```

## Using http-link-header-cpp

### After installing

Once `http-link-header-cpp` is installed, you can use it in your project with a simple cmake `find_package()` command. Be
sure to mark it as using `CONFIG` mode since we just installed those config files. Also mark it as required if your
project requires `http-link-header-cpp`.

```shell
find_package("http-link-header-cpp" CONFIG REQUIRED)
Explanations:
- `-DUSE_CONAN=ON`: tell `CMakeLists.txt` to load `conanbuildinfo.cmake` generated by the `conan install` command.
- `-GNinja`: Use Ninja instead of GNU Make. Remove this if you prefer using GNU Make as it is the default CMake generator.
- `-DCMAKE_PREFIX_PATH=$(pwd)`: Variable telling CMake where to find the generated config files for dependencies (i.e. `<lowercasePackageName>-config.cmake`)
- `-DCMAKE_BUILD_TYPE=Release`: Change it to `Debug` if you want to build the project with `-O0 -g`
- `-DCMAKE_INSTALL_PREFIX=$(pwd)/sysroot`: If `CMAKE_INSTALL_PREFIX` is not set, the default installation locations for `http-link-header-cpp` are `/usr/local/include` and `/usr/local/share`.

Build the project.
```txt
ninja
```

### Not installing
Run the unit tests.
```txt
ninja test
```

You can use `http-link-header-cpp` in your project without installing it at all. This will require a little more
configuration.
Install the build artifacts.
```txt
ninja install
```

Once you put the `http-link-header-cpp` files somewhere (likely within your own project), then you use
cmake's `add_subdirectory()`. You will want to make sure not to install `http-link-header-cpp` during your install process
by using the `EXCLUDE_FROM_ALL` option.
## Exporting the package into Conan cache

At the root of the package:
```shell
add_subdirectory(path/to/http-link-header-cpp ${PROJECT_BINARY_DIR}/http-link-header-cpp-build EXCLUDE_FROM_ALL)
conan create . http-link-header-cpp/0.9.0@conan/testing --build=missing
```

The package can be pulled in others packages depending on it by adding `http-link-header-cpp/0.9.0@conan/testing` as a build dependency.
4 changes: 0 additions & 4 deletions cmake/http-link-header-cppConfig.cmake.in

This file was deleted.

Loading