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

Add recipe for the LLVM core libraries #3375

Merged
merged 37 commits into from
May 24, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6c6d87b
Added recipe for the LLVM core libraries
newlawrence Nov 1, 2020
8e4e4d0
Reuse cmake configuration
newlawrence Nov 1, 2020
daa072b
Fix shared builds for 10x and 11x
newlawrence Nov 1, 2020
b735998
Parse dependencies from graphviz output
newlawrence Nov 2, 2020
edf9abc
Beware of dummy targets
newlawrence Nov 2, 2020
aebb740
Keep only latest version for the moment
newlawrence Nov 2, 2020
6fdd6a6
Beware of Windows line endings
newlawrence Nov 3, 2020
00c52c8
Relax cmake version requirement
newlawrence Nov 3, 2020
41562aa
Add list of unsupported compiler configurations
newlawrence Nov 3, 2020
d876521
Commit suggestion
newlawrence Nov 3, 2020
9cb7274
Cannot discriminate Visual Studio by its minor version
newlawrence Nov 4, 2020
d8286db
Disable object targets properly
newlawrence Nov 4, 2020
b9347da
Use external dependencies properly
newlawrence Nov 5, 2020
881ce17
Enable building with libffi in Windows
newlawrence Nov 5, 2020
d0c2201
Do not force libc++ in clang builds
newlawrence Nov 6, 2020
329d69e
Wrong value for a cmake flag
newlawrence Nov 6, 2020
d876b34
Building native tools were making some configurations fail
newlawrence Nov 6, 2020
c9a784c
Allow Visual Studio generators now that native tools are disabled
newlawrence Nov 6, 2020
cf7b3c0
Disable relative paths for the sources in the debug info
newlawrence Nov 6, 2020
8ce9dec
Update supported compilers
newlawrence Nov 7, 2020
01e6a26
String comparisons are dangerous
newlawrence Nov 7, 2020
33c36f2
Remove iconv patch comment
newlawrence Nov 7, 2020
bb7baec
Commit suggestion
newlawrence Nov 8, 2020
59d8248
More meaningful exception messages
newlawrence Nov 8, 2020
1ef186a
Remove unnecessary readme
newlawrence Nov 8, 2020
d30f900
Support older Python versions
newlawrence Nov 11, 2020
7c9f6ef
Empty commit to trigger the CI
newlawrence Nov 22, 2020
304a14e
Remove unnecessary status message
newlawrence Jan 4, 2021
563e571
Less strict cmake minimum required version
newlawrence Jan 4, 2021
e79842e
LLVM version bumped to 11.0.1
newlawrence Jan 16, 2021
c0ab4e7
LLVM version bumped to 11.1.0
newlawrence Apr 7, 2021
194cf21
Deactivate fPIC if shared
newlawrence Apr 9, 2021
e021639
Fix fPIC flag for shared builds
newlawrence Apr 12, 2021
d99091d
Install LLVMTableGenGlobalISel manually
newlawrence Apr 12, 2021
c4ae50c
Add option use_sanitizer
newlawrence May 21, 2021
e5b2dee
Disable all shared builds
newlawrence May 21, 2021
f6a023b
Dedent conandata.yml
newlawrence May 22, 2021
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
8 changes: 8 additions & 0 deletions recipes/llvm-core/all/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.14)
project(conanllvm)

message(STATUS "Conan CMake Wrapper")
newlawrence marked this conversation as resolved.
Show resolved Hide resolved
include(${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

add_subdirectory("source")
41 changes: 41 additions & 0 deletions recipes/llvm-core/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
sources:
"11.0.0":
url: https://github.com/llvm/llvm-project/releases/download/llvmorg-11.0.0/llvm-11.0.0.src.tar.xz
sha256: 913f68c898dfb4a03b397c5e11c6a2f39d0f22ed7665c9cefa87a34423a72469

"10.0.1":
url: https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.1/llvm-10.0.1.src.tar.xz
sha256: c5d8e30b57cbded7128d78e5e8dad811bff97a8d471896812f57fa99ee82cdf3

"10.0.0":
url: https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/llvm-10.0.0.src.tar.xz
sha256: df83a44b3a9a71029049ec101fb0077ecbbdf5fe41e395215025779099a98fdf

"9.0.1":
url: https://github.com/llvm/llvm-project/releases/download/llvmorg-9.0.1/llvm-9.0.1.src.tar.xz
sha256: 00a1ee1f389f81e9979f3a640a01c431b3021de0d42278f6508391a2f0b81c9a
newlawrence marked this conversation as resolved.
Show resolved Hide resolved

patches:
"11.0.0":
- base_path: "source"
patch_file: "patches/11x-vs2019.patch"
- base_path: "source"
patch_file: "patches/11x-cmake.patch"

"10.0.1":
- base_path: "source"
patch_file: "patches/10x-vs2019.patch"
- base_path: "source"
patch_file: "patches/10x-cmake.patch"

"10.0.0":
- base_path: "source"
patch_file: "patches/10x-vs2019.patch"
- base_path: "source"
patch_file: "patches/10x-cmake.patch"

"9.0.1":
- base_path: "source"
patch_file: "patches/9x-vs2019.patch"
- base_path: "source"
patch_file: "patches/9x-cmake.patch"
258 changes: 258 additions & 0 deletions recipes/llvm-core/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
from conans.errors import ConanInvalidConfiguration
from conans import ConanFile, CMake, tools

from pathlib import Path
from collections import defaultdict
import json
import re
import os


class LLVMCoreConan(ConanFile):
name = 'llvm-core'
description = (
'A toolkit for the construction of highly optimized compilers,'
'optimizers, and runtime environments.'
)
license = 'Apache-2.0 WITH LLVM-exception'
Copy link
Contributor

Choose a reason for hiding this comment

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

As a remark for all reviewers (and my future self), this is actually the correct SPDX annotation 👍

topics = ('conan', 'llvm')
homepage = 'https://github.com/llvm/llvm-project/tree/master/llvm'
url = 'https://github.com/conan-io/conan-center-index'

settings = ('os', 'arch', 'compiler', 'build_type')
options = {
'shared': [True, False],
'fPIC': [True, False],
'components': 'ANY',
'targets': 'ANY',
'exceptions': [True, False],
'rtti': [True, False],
'threads': [True, False],
'lto': ['On', 'Off', 'Full', 'Thin'],
'static_stdlib': [True, False],
'unwind_tables': [True, False],
'expensive_checks': [True, False],
'use_perf': [True, False],
'with_zlib': [True, False],
'with_xml2': [True, False],
'with_ffi': [True, False]
}
default_options = {
'shared': False,
'fPIC': True,
'components': 'all',
'targets': 'all',
'exceptions': True,
'rtti': True,
'threads': True,
'lto': 'Off',
'static_stdlib': False,
'unwind_tables': True,
'expensive_checks': False,
'use_perf': False,
'with_zlib': True,
'with_xml2': True,
'with_ffi': False
}

exports_sources = ['CMakeLists.txt', 'patches/*']
generators = 'cmake'
no_copy_source = True

_source_subfolder = 'source'
newlawrence marked this conversation as resolved.
Show resolved Hide resolved

def _configure_cmake(self):
if self.settings.compiler == 'Visual Studio':
generator = os.getenv('CONAN_CMAKE_GENERATOR', 'NMake Makefiles')
cmake = CMake(self, generator=generator)
else:
cmake = CMake(self)

cmake.definitions['BUILD_SHARED_LIBS'] = False
cmake.definitions['CMAKE_SKIP_RPATH'] = True

cmake.definitions['LLVM_TARGETS_TO_BUILD'] = self.options.targets
cmake.definitions['LLVM_TARGET_ARCH'] = 'host'
cmake.definitions['LLVM_BUILD_LLVM_DYLIB'] = self.options.shared
cmake.definitions['LLVM_ENABLE_PIC'] = \
self.options.get_safe('fPIC', default=False)
cmake.definitions['LLVM_DYLIB_COMPONENTS'] = \
self.options.get_safe('components', default='all')

cmake.definitions['LLVM_ABI_BREAKING_CHECKS'] = 'WITH_ASSERTS'
cmake.definitions['LLVM_ENABLE_WARNINGS'] = True
cmake.definitions['LLVM_ENABLE_PEDANTIC'] = True
cmake.definitions['LLVM_ENABLE_WERROR'] = False
cmake.definitions['LLVM_ENABLE_LIBCXX'] = \
'clang' in str(self.settings.compiler)

cmake.definitions['LLVM_USE_RELATIVE_PATHS_IN_DEBUG_INFO'] = True
cmake.definitions['LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN'] = False
cmake.definitions['LLVM_BUILD_INSTRUMENTED_COVERAGE'] = False
cmake.definitions['LLVM_OPTIMIZED_TABLEGEN'] = True
cmake.definitions['LLVM_REVERSE_ITERATION'] = False
cmake.definitions['LLVM_ENABLE_BINDINGS'] = False
cmake.definitions['LLVM_CCACHE_BUILD'] = False

cmake.definitions['LLVM_INCLUDE_TOOLS'] = self.options.shared
cmake.definitions['LLVM_INCLUDE_EXAMPLES'] = False
cmake.definitions['LLVM_INCLUDE_TESTS'] = False
cmake.definitions['LLVM_INCLUDE_BENCHMARKS'] = False
cmake.definitions['LLVM_APPEND_VC_REV'] = False
cmake.definitions['LLVM_BUILD_DOCS'] = False
cmake.definitions['LLVM_ENABLE_IDE'] = False

cmake.definitions['LLVM_ENABLE_EH'] = self.options.exceptions
cmake.definitions['LLVM_ENABLE_RTTI'] = self.options.rtti
cmake.definitions['LLVM_ENABLE_THREADS'] = self.options.threads
cmake.definitions['LLVM_ENABLE_LTO'] = self.options.lto
cmake.definitions['LLVM_STATIC_LINK_CXX_STDLIB'] = \
self.options.static_stdlib
cmake.definitions['LLVM_ENABLE_UNWIND_TABLES'] = \
self.options.unwind_tables
cmake.definitions['LLVM_ENABLE_EXPENSIVE_CHECKS'] = \
self.options.expensive_checks
cmake.definitions['LLVM_ENABLE_ASSERTIONS'] = \
self.settings.build_type == 'Debug'

cmake.definitions['LLVM_USE_NEWPM'] = False
cmake.definitions['LLVM_USE_OPROFILE'] = False
cmake.definitions['LLVM_USE_PERF'] = self.options.use_perf

cmake.definitions['LLVM_ENABLE_Z3_SOLVER'] = False
cmake.definitions['LLVM_ENABLE_LIBPFM'] = False
cmake.definitions['LLVM_ENABLE_LIBEDIT'] = False

cmake.definitions['LLVM_ENABLE_ZLIB'] = \
self.options.get_safe('with_zlib', False)
cmake.definitions['LLVM_ENABLE_LIBXML2'] = \
self.options.get_safe('with_xml2', False)
cmake.definitions['LLVM_ENABLE_FFI'] = \
self.options.get_safe('with_ffi', False)
if self.options.get_safe('with_ffi', False):
cmake.definitions['FFI_INCLUDE_DIR'] = \
self.deps_cpp_info['libffi'].include_paths[0]
cmake.definitions['FFI_LIBRARY_DIR'] = \
self.deps_cpp_info['libffi'].lib_paths[0]
return cmake

def config_options(self):
if self.settings.os == 'Windows':
del self.options.fPIC
del self.options.components
del self.options.with_zlib
del self.options.with_xml2
del self.options.with_ffi

def requirements(self):
if self.options.get_safe('with_zlib', False):
self.requires('zlib/1.2.11')
if self.options.get_safe('with_xml2', False):
self.requires('libxml2/2.9.10')
if self.options.get_safe('with_ffi', False):
self.requires('libffi/3.3')

def configure(self):
if self.settings.os == 'Windows' and self.options.shared:
raise ConanInvalidConfiguration('shared lib not supported')
newlawrence marked this conversation as resolved.
Show resolved Hide resolved
if self.options.exceptions and not self.options.rtti:
raise ConanInvalidConfiguration('exceptions require rtti support')

def source(self):
tools.get(**self.conan_data['sources'][self.version])
source_path = Path(f'llvm-{self.version}.src')
source_path.rename(self._source_subfolder)

if self.version in self.conan_data['patches']:
for patch in self.conan_data['patches'][self.version]:
tools.patch(**patch)

def build(self):
cmake = self._configure_cmake()
cmake.configure()
cmake.build()

def package(self):
self.copy('LICENSE.TXT', dst='licenses', src=self._source_subfolder)
package_path = Path(self.package_folder)

cmake = self._configure_cmake()
cmake.install()

if not self.options.shared:
self.run('cmake --graphviz=graph/llvm.dot .')
with tools.chdir('graph'):
dot_text = tools.load('llvm.dot').replace(' ', '')

dep_regex = re.compile(r'//(.+)->(.+)$', re.MULTILINE)
deps = re.findall(dep_regex, dot_text)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you think about this @intelligide? Instead of parsing LLVMExports.cmake, I use cmake to output the dependency graph as a graphviz's dot file which is way easier to parse.

It still uses a regular expression, but it is a simple one. The alternative would be using external tools like graphviz plus networkx that will do the parsing for you, but then you'll introduce a dependency on those tools that may not be installed along conan. I think this solution is easy and maintainable enough.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's better (not perfect yet but better than nothing).


components = defaultdict(list)
for lib, dep in deps:
if not lib.startswith('LLVM'):
continue
elif dep.startswith('llvm-') or dep.startswith('-delayload:'):
continue
elif dep.startswith('LLVM'):
components[dep]
elif Path(dep).exists():
dep = Path(dep).stem.replace('lib', '')
components[lib].append(dep.replace('-l', ''))

tools.rmdir(str(package_path.joinpath('bin').resolve()))
tools.rmdir(str(package_path.joinpath('lib', 'cmake').resolve()))
tools.rmdir(str(package_path.joinpath('share').resolve()))

for file in package_path.joinpath('lib').iterdir():
if 'LLVM' not in file.stem:
file.unlink()

if not self.options.shared:
components_path = package_path.joinpath('lib', 'components.json')
with components_path.open(mode='w') as file:
json.dump(components, file, indent=4)
else:
suffixes = ['.dylib', '.so']
for file in package_path.joinpath('lib').iterdir():
if not any(suffix in file.suffixes for suffix in suffixes):
file.unlink()

def package_info(self):
if self.options.shared:
self.cpp_info.libs = tools.collect_libs(self)
if self.settings.os == 'Linux':
self.cpp_info.system_libs = ['tinfo', 'pthread']
self.cpp_info.system_libs.extend(['rt', 'dl', 'm'])
elif self.settings.os == 'Macos':
self.cpp_info.system_libs = ['curses', 'm']
return

package_path = Path(self.package_folder)
components_path = package_path.joinpath('lib', 'components.json')
with components_path.open(mode='r') as file:
components = json.load(file)

dependencies = ['z', 'iconv', 'xml2', 'ffi']
targets = {
'z': 'zlib::zlib',
'xml2': 'libxml2::libxml2',
'ffi': 'libffi::libffi'
}

for lib, deps in components.items():
component = lib[4:].replace('LLVM', '').lower()

self.cpp_info.components[component].libs = [lib]

self.cpp_info.components[component].requires = [
dep[4:].replace('LLVM', '').lower()
for dep in deps if dep.startswith('LLVM')
]
for lib, target in targets.items():
if lib in deps:
self.cpp_info.components[component].requires.append(target)

self.cpp_info.components[component].system_libs = [
dep for dep in deps
if not dep.startswith('LLVM') and dep not in dependencies
]
39 changes: 39 additions & 0 deletions recipes/llvm-core/all/patches/10x-cmake.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
--- cmake/config-ix.cmake
+++ cmake/config-ix.cmake
@@ -166,6 +166,7 @@
else()
include_directories(${LIBXML2_INCLUDE_DIR})
endif()
+ set(LIBXML2_LIBRARIES "xml2;iconv;z")
endif()
endif()
endif()
@@ -319,7 +319,7 @@
message(FATAL_ERROR "libffi includes are not found.")
endif()

- find_library(FFI_LIBRARY_PATH ffi PATHS ${FFI_LIBRARY_DIR})
+ find_library(FFI_LIBRARY_PATH NAMES ffi libffi PATHS ${FFI_LIBRARY_DIR})
if( NOT FFI_LIBRARY_PATH )
message(FATAL_ERROR "libffi is not found.")
endif()
--- lib/WindowsManifest/CMakeLists.txt
+++ lib/WindowsManifest/CMakeLists.txt
@@ -8,16 +8,6 @@
if(LIBXML2_LIBRARIES)
target_link_libraries(LLVMWindowsManifest PUBLIC ${LIBXML2_LIBRARIES})

- get_filename_component(xml2_library ${LIBXML2_LIBRARIES} NAME)
- if (CMAKE_STATIC_LIBRARY_PREFIX AND
- xml2_library MATCHES "^${CMAKE_STATIC_LIBRARY_PREFIX}.*${CMAKE_STATIC_LIBRARY_SUFFIX}$")
- string(REGEX REPLACE "^${CMAKE_STATIC_LIBRARY_PREFIX}" "" xml2_library ${xml2_library})
- string(REGEX REPLACE "${CMAKE_STATIC_LIBRARY_SUFFIX}$" "" xml2_library ${xml2_library})
- elseif (CMAKE_SHARED_LIBRARY_PREFIX AND
- xml2_library MATCHES "^${CMAKE_SHARED_LIBRARY_PREFIX}.*${CMAKE_SHARED_LIBRARY_SUFFIX}$")
- string(REGEX REPLACE "^${CMAKE_SHARED_LIBRARY_PREFIX}" "" xml2_library ${xml2_library})
- string(REGEX REPLACE "${CMAKE_SHARED_LIBRARY_SUFFIX}$" "" xml2_library ${xml2_library})
- endif()
set_property(TARGET LLVMWindowsManifest PROPERTY
- LLVM_SYSTEM_LIBS ${xml2_library})
+ LLVM_SYSTEM_LIBS ${LIBXML2_LIBRARIES})
endif()
11 changes: 11 additions & 0 deletions recipes/llvm-core/all/patches/10x-vs2019.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- include/llvm/Support/type_traits.h
+++ include/llvm/Support/type_traits.h
@@ -177,7 +177,7 @@
(has_deleted_copy_assign || has_trivial_copy_assign) &&
(has_deleted_copy_constructor || has_trivial_copy_constructor);

-#ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE
+#if 0
static_assert(value == std::is_trivially_copyable<T>::value,
"inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
#endif
Loading