Skip to content

Commit

Permalink
llvm-openmp: match the output of FindOpenMP.cmake
Browse files Browse the repository at this point in the history
  • Loading branch information
valgur committed Jan 17, 2024
1 parent 29b48ab commit bb43094
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 34 deletions.
128 changes: 128 additions & 0 deletions recipes/llvm-openmp/all/cmake/conan-llvm-openmp-vars.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Loosely based on https://github.com/Kitware/CMake/blob/69b562c/Modules/FindOpenMP.cmake

set(OpenMP_C_FLAGS "@OpenMP_FLAGS@")
set(OpenMP_C_INCLUDE_DIR "${OpenMP_INCLUDE_DIR}")
set(OpenMP_C_INCLUDE_DIRS "${OpenMP_INCLUDE_DIRS}")
set(OpenMP_C_LIB_NAMES "@OpenMP_LIB_NAMES@")
set(OpenMP_C_LIBRARIES "${OpenMP_LIBRARIES}")
set(OpenMP_C_DEFINITIONS "${OpenMP_DEFINITIONS}")

set(OpenMP_CXX_FLAGS "@OpenMP_FLAGS@")
set(OpenMP_CXX_INCLUDE_DIR "${OpenMP_INCLUDE_DIR}")
set(OpenMP_CXX_INCLUDE_DIRS "${OpenMP_INCLUDE_DIRS}")
set(OpenMP_CXX_LIB_NAMES "@OpenMP_LIB_NAMES@")
set(OpenMP_CXX_LIBRARIES "${OpenMP_LIBRARIES}")
set(OpenMP_CXX_DEFINITIONS "${OpenMP_DEFINITIONS}")

set(OpenMP_omp_LIBRARY "${OpenMP_LIBRARIES}")

set(OpenMP_FOUND FALSE)
set(OPENMP_FOUND FALSE)
set(OPENMP_FOUND FALSE)
set(OpenMP_C_FOUND FALSE)
set(OpenMP_CXX_FOUND FALSE)
set(OpenMP_Fortran_FOUND FALSE)

# Determine OpenMP specification date and version
function(_openmp_get_spec_date)
set(SRC_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver.c")
set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver.bin")
file(WRITE "${SRC_FILE}" "
#include <stdio.h>
#include <omp.h>
#define STRINGIFY(x) #x
#define TO_STRING(x) STRINGIFY(x)
const char ompver_str[] = \"INFO:OpenMP-date[\" TO_STRING(_OPENMP) \"]\";
int main(void)
{
puts(ompver_str);
return 0;
}
")
try_compile(OpenMP_SPECTEST
SOURCES "${SRC_FILE}"
LOG_DESCRIPTION "Detecting OpenMP version"
CMAKE_FLAGS
"-DCOMPILE_DEFINITIONS:STRING=${OpenMP_C_FLAGS}"
"-DINCLUDE_DIRECTORIES:STRING=${OpenMP_INCLUDE_DIR}"
"-DLINK_DIRECTORIES:STRING=${OpenMP_INCLUDE_DIR}/../lib"
"-DLINK_LIBRARIES:STRING=${OpenMP_C_LIB_NAMES}"
COPY_FILE "${BIN_FILE}"
)
file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date")
if(specstr MATCHES ".*INFO:OpenMP-date\\[0*([^]]*)\\].*")
set(OpenMP_SPEC_DATE ${CMAKE_MATCH_1} PARENT_SCOPE)
else()
if(OpenMP_FIND_REQUIRED)
message(FATAL_ERROR "Failed to detect OpenMP specification date")
elseif(NOT OpenMP_FIND_QUIETLY)
message(SEND_ERROR "Failed to detect OpenMP specification date")
endif()
return()
endif()
endfunction()

function(_openmp_set_version_by_spec_date)
set(OpenMP_SPEC_DATE_MAP
"202111=5.2"
"202011=5.1"
"201811=5.0"
"201511=4.5"
"201307=4.0"
"201107=3.1"
"200805=3.0"
"200505=2.5"
"200203=2.0"
"200011=2.0"
"199911=1.1"
)
if(OpenMP_SPEC_DATE_MAP MATCHES "${OpenMP_SPEC_DATE}=([0-9]+)\\.([0-9]+)")
set(major "${CMAKE_MATCH_1}")
set(minor "${CMAKE_MATCH_2}")
else()
if(OpenMP_FIND_REQUIRED)
message(FATAL_ERROR "Failed to detect OpenMP specification version")
elseif(NOT OpenMP_FIND_QUIETLY)
message(SEND_ERROR "Failed to detect OpenMP specification version")
endif()
return()
endif()
set(OpenMP_VERSION_MAJOR "${major}" PARENT_SCOPE)
set(OpenMP_VERSION_MINOR "${minor}" PARENT_SCOPE)
set(OpenMP_VERSION "${major}.${minor}" PARENT_SCOPE)
endfunction()

_openmp_get_spec_date()
_openmp_set_version_by_spec_date()

set(OpenMP_C_FOUND TRUE)
set(OpenMP_C_SPEC_DATE "${OpenMP_SPEC_DATE}")
set(OpenMP_C_VERSION_MAJOR "${OpenMP_VERSION_MAJOR}")
set(OpenMP_C_VERSION_MINOR "${OpenMP_VERSION_MINOR}")
set(OpenMP_C_VERSION "${OpenMP_VERSION}")

set(OpenMP_CXX_FOUND TRUE)
set(OpenMP_CXX_SPEC_DATE "${OpenMP_SPEC_DATE}")
set(OpenMP_CXX_VERSION_MAJOR "${OpenMP_VERSION_MAJOR}")
set(OpenMP_CXX_VERSION_MINOR "${OpenMP_VERSION_MINOR}")
set(OpenMP_CXX_VERSION "${OpenMP_VERSION}")

# Check specification version against the requested min version, validate components
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenMP
VERSION_VAR OpenMP_C_VERSION
REQUIRED_VARS
OpenMP_C_FLAGS
OpenMP_C_LIB_NAMES
OpenMP_C_SPEC_DATE
OpenMP_C_VERSION
OpenMP_CXX_FLAGS
OpenMP_CXX_LIB_NAMES
OpenMP_CXX_SPEC_DATE
OpenMP_CXX_VERSION
HANDLE_COMPONENTS
)

set(OPENMP_FOUND ${OpenMP_FOUND})
set(OpenMP_C_FOUND ${OpenMP_FOUND})
set(OpenMP_CXX_FOUND ${OpenMP_FOUND})
81 changes: 48 additions & 33 deletions recipes/llvm-openmp/all/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from conan.tools.build import check_min_cppstd
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan.tools.env import VirtualBuildEnv
from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, replace_in_file, save, move_folder_contents, rmdir
from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, replace_in_file, save, move_folder_contents, rmdir, load, save

Check warning on line 10 in recipes/llvm-openmp/all/conanfile.py

View workflow job for this annotation

GitHub Actions / Lint changed conanfile.py (v2 migration)

Reimport 'save' (imported line 10)
from conan.tools.microsoft import is_msvc
from conan.tools.scm import Version

Expand Down Expand Up @@ -60,6 +60,7 @@ def _version_major(self):

def export_sources(self):
export_conandata_patches(self)
copy(self, "*.cmake.in", self.recipe_folder, self.export_sources_folder)

def config_options(self):
if self.settings.os == "Windows":
Expand All @@ -80,7 +81,7 @@ def validate(self):
if is_msvc(self):
raise ConanInvalidConfiguration("llvm-openmp is not compatible with MSVC")

if not self._openmp_flags():
if not self._openmp_flags:
raise ConanInvalidConfiguration(
f"{self.settings.compiler} is not supported by this recipe. Contributions are welcome!"
)
Expand Down Expand Up @@ -146,6 +147,37 @@ def build(self):
cmake.configure()
cmake.build()

@property
def _module_file_rel_path(self):
return os.path.join("lib", "cmake", "openmp", "conan-llvm-openmp-vars.cmake")

@property
def _conan1_targets_module_file_rel_path(self):
return os.path.join("lib", "cmake", "openmp", f"conan-official-{self.name}-targets.cmake")

@property
def _openmp_flags(self):
# Based on https://github.com/Kitware/CMake/blob/v3.28.1/Modules/FindOpenMP.cmake#L104-L135
if self.settings.compiler == "clang":
return ["-fopenmp=libomp"]
elif self.settings.compiler == "apple-clang":
return ["-Xclang", "-fopenmp"]
elif self.settings.compiler == "gcc":
return ["-fopenmp"]
elif self.settings.compiler == "intel-cc":
return ["-Qopenmp"]
elif self.settings.compiler == "sun-cc":
return ["-xopenmp"]
elif is_msvc(self):
return ["-openmp"]
return None

@property
def _system_libs(self):
if self.settings.os in ["Linux", "FreeBSD"]:
return ["m", "dl", "pthread", "rt"]
return []

def package(self):
copy(self, "LICENSE.txt",
src=self.source_folder,
Expand All @@ -154,9 +186,14 @@ def package(self):
cmake.install()
rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))

cmake_module = load(self, os.path.join(self.export_sources_folder, "cmake", "conan-llvm-openmp-vars.cmake.in"))
cmake_module = cmake_module.replace("@OpenMP_FLAGS@", " ".join(self._openmp_flags))
cmake_module = cmake_module.replace("@OpenMP_LIB_NAMES@", ";".join(["omp"] + self._system_libs))
save(self, os.path.join(self.package_folder, self._module_file_rel_path), cmake_module)

# TODO: to remove in conan v2 once cmake_find_package* generators removed
self._create_cmake_module_alias_targets(
os.path.join(self.package_folder, self._module_file_rel_path),
os.path.join(self.package_folder, self._conan1_targets_module_file_rel_path),
{
"OpenMP::OpenMP_C": "OpenMP::OpenMP",
"OpenMP::OpenMP_CXX": "OpenMP::OpenMP",
Expand All @@ -174,46 +211,24 @@ def _create_cmake_module_alias_targets(self, module_file, targets):
""")
save(self, module_file, content)

@property
def _module_file_rel_path(self):
return os.path.join("lib", "cmake", f"conan-official-{self.name}-targets.cmake")

def _openmp_flags(self):
# Based on https://github.com/Kitware/CMake/blob/v3.28.1/Modules/FindOpenMP.cmake#L104-L135
if self.settings.compiler == "clang":
return ["-fopenmp=libomp"]
elif self.settings.compiler == "apple-clang":
return ["-Xclang", "-fopenmp"]
elif self.settings.compiler == "gcc":
return ["-fopenmp"]
elif self.settings.compiler == "intel-cc":
return ["-Qopenmp"]
elif self.settings.compiler == "sun-cc":
return ["-xopenmp"]
elif is_msvc(self):
return ["-openmp"]
return None

def package_info(self):
# Match FindOpenMP.cmake module provided by CMake
self.cpp_info.set_property("cmake_find_mode", "both")
self.cpp_info.set_property("cmake_file_name", "OpenMP")
self.cpp_info.set_property("cmake_target_name", "OpenMP::OpenMP")
self.cpp_info.set_property("cmake_target_aliases", ["OpenMP::OpenMP_C", "OpenMP::OpenMP_CXX"])

openmp_flags = self._openmp_flags()
self.cpp_info.cflags = openmp_flags
self.cpp_info.cxxflags = openmp_flags
self.cpp_info.sharedlinkflags = openmp_flags
self.cpp_info.exelinkflags = openmp_flags

self.cpp_info.libs = ["omp"]
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.system_libs = ["dl", "m", "pthread", "rt"]
self.cpp_info.system_libs = self._system_libs
self.cpp_info.cflags = self._openmp_flags
self.cpp_info.cxxflags = self._openmp_flags

self.cpp_info.builddirs.append(os.path.join(self.package_folder, "lib", "cmake", "openmp"))
self.cpp_info.set_property("cmake_build_modules", [self._module_file_rel_path])

# TODO: to remove in conan v2 once cmake_find_package* generators removed
self.cpp_info.names["cmake_find_package"] = "OpenMP"
self.cpp_info.names["cmake_find_package_multi"] = "OpenMP"
self.cpp_info.builddirs.append(os.path.join(self.package_folder, "lib", "cmake"))
self.cpp_info.build_modules["cmake_find_package"] = [self._module_file_rel_path]
self.cpp_info.build_modules["cmake_find_package_multi"] = [self._module_file_rel_path]
self.cpp_info.build_modules["cmake_find_package"] = [self._module_file_rel_path, self._conan1_targets_module_file_rel_path]
self.cpp_info.build_modules["cmake_find_package_multi"] = [self._module_file_rel_path, self._conan1_targets_module_file_rel_path]
29 changes: 28 additions & 1 deletion recipes/llvm-openmp/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
cmake_minimum_required(VERSION 3.15)
project(PackageTest CXX C)

find_package(OpenMP MODULE REQUIRED)
find_package(OpenMP CONFIG COMPONENTS Fortran QUIET)
if(OpenMP_FOUND)
message(FATAL_ERROR "OpenMP should have failed to find Fortran.")
endif()

# FIXME: Conan seems to override the OpenMP_FOUND variable to TRUE in MODULE mode
# find_package(OpenMP MODULE COMPONENTS Fortran QUIET)
# if(OpenMP_FOUND)
# message(FATAL_ERROR "OpenMP should have failed to find Fortran.")
# endif()

find_package(OpenMP MODULE REQUIRED COMPONENTS C CXX)

message("OpenMP_FOUND: ${OpenMP_CXX_FOUND}")
message("OpenMP_VERSION: ${OpenMP_VERSION}")
message("OpenMP_C_FOUND: ${OpenMP_CXX_FOUND}")
message("OpenMP_CXX_FOUND: ${OpenMP_CXX_FOUND}")
message("OpenMP_CXX_VERSION: ${OpenMP_CXX_VERSION}")
message("OpenMP_CXX_SPEC_DATE: ${OpenMP_CXX_SPEC_DATE}")
message("OpenMP_CXX_INCLUDE_DIRS: ${OpenMP_CXX_INCLUDE_DIRS}")
message("OpenMP_CXX_LIB_NAMES: ${OpenMP_CXX_LIB_NAMES}")
message("OpenMP_CXX_LIBRARIES: ${OpenMP_CXX_LIBRARIES}")
message("OpenMP_CXX_FLAGS: ${OpenMP_CXX_FLAGS}")
message("OpenMP_omp_LIBRARY: ${OpenMP_omp_LIBRARY}")

if(NOT DEFINED OpenMP_CXX_SPEC_DATE)
message(FATAL_ERROR "FindOpenMP.cmake did not set all variables correctly.")
endif()

add_executable(test_package_cxx test_package.cpp)
target_link_libraries(test_package_cxx OpenMP::OpenMP_CXX)
Expand Down

0 comments on commit bb43094

Please sign in to comment.