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

CMake update to find liblz4 using pkg-config instead of cmake. #46

Merged
merged 9 commits into from
Feb 9, 2024
29 changes: 14 additions & 15 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
##########################################################

# minimum version of CMake, which is determined by Geant4's requirements
cmake_minimum_required(VERSION 3.14)
cmake_minimum_required(VERSION 3.20)

project(HIPO VERSION 4.0.1)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

#
# Set a default build type if none was specified
#
Expand Down Expand Up @@ -60,25 +61,21 @@ find_package(LZ4 QUIET CONFIG PATHS ${PROJECT_SOURCE_DIR}/cmake )

if(NOT LZ4_FOUND)
message(STATUS "**LZ4********************************************************************")
message(STATUS "* We did not find a system LZ4 package -- We will build this locally. *")
message(STATUS "* We did not find a system (or local build) LZ4 package. *")
message(STATUS "* Please install lz4 (Centos: yum install lz4 MacOS: brew install lz4) *")
message(STATUS "* Or build lz4 from the included sources. *")
message(STATUS "* *")
message(STATUS "* To make this possible, please make sure you initialized the submodule.*")
message(STATUS "* If you did not include --recurse-submodules at initial clone do: *")
message(STATUS "* git submodule init *")
message(STATUS "* git submodule update *")
message(STATUS "* Then: 'cd lz4' followed by: *")
message(STATUS "* make PREFIX=${CMAKE_INSTALL_PREFIX} CFLAGS='-fPIC' install ")
message(STATUS "*************************************************************************")
message("PROJECT_SOURCE_DIR = ${PROJECT_SOURCE_DIR}")
file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/include/hipo4)
add_custom_target(LZ4 ALL
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/lz4/lib
COMMAND make PREFIX=${CMAKE_INSTALL_PREFIX} CFLAGS="-fPIC" install
)

set(LZ4_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/include)
set(LZ4_LIBRARIES ${CMAKE_INSTALL_PREFIX}/lib/liblz4.a)
message(FATAL_ERROR "stop processing until lz4 is available")
endif()

add_compile_definitions(__LZ4__)
include_directories(${LZ4_INCLUDE_DIRS})

set(DATAFRAME_IN_MAIN TRUE)
add_subdirectory(extensions/dataframes)
Expand Down Expand Up @@ -129,7 +126,9 @@ set_target_properties(hipo4_static PROPERTIES OUTPUT_NAME hipo4) # So that the

# Required on Unix OS family to be able to be linked into shared libraries.
set_target_properties(hipo4_objs PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_dependencies(hipo4_objs LZ4)
# Note: Neither add_dependencies(hipo4_objs PkgConfig::LZ4) nor target_include_directories(hipo4_objs PUBLIC PkgConfig::LZ4)
# work in an Intel Mac.
target_include_directories(hipo4_objs PUBLIC ${LZ4_INCLUDE_DIRS})

# Include the macros for creating export package.
include(CMakePackageConfigHelpers)
Expand All @@ -144,8 +143,8 @@ target_include_directories(hipo4 PUBLIC
$<INSTALL_INTERFACE:include/hipo4>
)

target_link_libraries(hipo4 PUBLIC ${LZ4_LIBRARIES} )
target_link_libraries(hipo4_static PUBLIC ${LZ4_LIBRARIES})
target_link_libraries(hipo4 PUBLIC PkgConfig::LZ4 )
target_link_libraries(hipo4_static PUBLIC PkgConfig::LZ4)

install(TARGETS hipo4
EXPORT hipo4-export
Expand Down
38 changes: 6 additions & 32 deletions cmake/LZ4Config.cmake
Original file line number Diff line number Diff line change
@@ -1,41 +1,15 @@
#
# Find the LZ4 library and include files and configure target for it.
#
get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
find_path(LZ4_INCLUDE_DIR NAMES lz4.h)
find_library(LZ4_LIBRARY NAMES lz4)
if (LZ4_LIBRARY)
include(CheckCSourceRuns)
set(CMAKE_REQUIRED_INCLUDES ${LZ4_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${LZ4_LIBRARY})
enable_language(C)
check_c_source_runs("
#include <lz4.h>
int main() {
int good = (LZ4_VERSION_MAJOR > 1) ||
((LZ4_VERSION_MAJOR == 1) && (LZ4_VERSION_MINOR >= 8));
return !good;
}" LZ4_GOOD_VERSION)
set(CMAKE_REQUIRED_INCLUDES)
set(CMAKE_REQUIRED_LIBRARIES)
endif()

include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(
LZ4 DEFAULT_MSG
LZ4_LIBRARY LZ4_INCLUDE_DIR LZ4_GOOD_VERSION)
set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")

Is this needed? I think CMake's PkgConfig module will search CMAKE_PREFIX_PATH's lib/pkgconfig subdirectories by default, so you just need to make sure LZ4's top-level installation prefix is in CMAKE_PREFIX_PATH (and if LZ4 is installed at the system level, then it's not necessary to add the system directories since they will already be searched).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, "needed" it is not. If lz4 is properly installed it all works. However if the user installs lz4 from the directory included with hipo, then this line avoids the confusion with cmake not finding that install unless you also set the CMAKE_PREFIX_PATH. I would think that "expected behavior" is that cmake just finds the package files, as it would if we used a cmake install instead of pkgconfig. It seems a simple fix to me, but if anyone objects I am fine without it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me

find_package(PkgConfig REQUIRED)
pkg_check_modules(LZ4 IMPORTED_TARGET "liblz4")

if (NOT LZ4_FOUND)
message(STATUS "No system version of LZ4 found.")
else()
if(NOT TARGET LZ4)
add_library(LZ4 INTERFACE IMPORTED)
set_target_properties(LZ4 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${LZ4_INCLUDE_DIR}"
)
endif()
message(STATUS "Found LZ4: ${LZ4_LIBRARY}")
set(LZ4_INCLUDE_DIRS ${LZ4_INCLUDE_DIR})
set(LZ4_LIBRARIES ${LZ4_LIBRARY})
add_library(LZ4 INTERFACE IMPORTED)
set_target_properties(LZ4 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LZ4_INCLUDE_DIR}")
message(STATUS "Found LZ4: ${LZ4_LIBRARIES}")
mark_as_advanced(LZ4_INCLUDE_DIRS LZ4_INCLUDE_DIR LZ4_LIBRARIES LZ4_LIBRARY)
endif (NOT LZ4_FOUND)
1 change: 1 addition & 0 deletions cmake/hipo4.pc.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ libdir=${prefix}/lib
Name: hipo4
Description: High Performance Output data format for experimental physics
Version: @HIPO_VERSION@
Requires: liblz4 >= @LZ4_VERSION@
Libs: -L${libdir} -lhipo4
Cflags: -I${includedir}
14 changes: 11 additions & 3 deletions extensions/dataframes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ cd build
cmake -DCMAKE_INSTALL_PREFIX=/path/to/install/location ..
make -j8 install
```
This will install the hipo4 library (both .a and .so) in
This will install the hipo4 and HipoDataFrame libraries in
`/path/to/install/location/lib`

You can now load the library into root with:
Expand All @@ -42,7 +42,7 @@ root [0] .L libHipoDataFrame.so
and the .so with .dylib)

***NOTE***: On a system where the default compiler is NOT c++17 compatible, i.e. Linux at JLab,
you want to specify the compiler to cmake. You can do so with the following lines:
you have to specify the compiler to cmake. You can do so with the following lines:
```bash
module use /apps/modulefiles
module load gcc/9.3.0
Expand All @@ -58,13 +58,21 @@ currently C++17 compatible, so use the ROOT version installed in `~holtrop/root`

[See the ROOT documentation for RDataFrame](https://root.cern/doc/master/classROOT_1_1RDataFrame.html)

***Note***: The names of the Hipo schema are mangled to avoid :: and . (period) in the name, since
these indicate C++ namespace and class member. So instead of :: and . we use underscores (_).

The basics:

```bash
root
root [0] .L libHipoDataFrame.so
root [1] auto df = MakeHipoDataFrame("rec_clas_016214.evio.00000.hipo")
root [2] df.GetColumnNames() // Shows what is in the file.
root [3] auto h_px = df.Histo1D("REC::Particle.px")
root [3] auto h_px = df.Histo1D("REC_Particle_px")
root [4] h_px->DrawClone();
```
The result would be a histogram of the REC::Particle.px, i.e the x component of the particle momentum
for all particles in the events.

The ROOT RDataFrame is very versatile and is intended by the ROOT team as the future of
data analysis. [See more details on the ROOT website](https://root.cern/doc/master/classROOT_1_1RDataFrame.html).