Skip to content

Commit

Permalink
Add an option to build clang from source code and more.
Browse files Browse the repository at this point in the history
- new -DBUILD_LLVM cmake option to download and build LLVM and Clang when building wrapit
- use above option for macOS CI as clang 13 is no more available from homebrew
- remove test with julia-head, because it often needs a libcxxwrap_julia_jll that is not registered.
  • Loading branch information
grasph committed Feb 6, 2025
1 parent 2c86cf3 commit a28ab4d
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 102 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/test-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ jobs:
matrix:
version:
- '1.10'
- 'nightly'
os:
- ubuntu-latest
# - ubuntu-latest
- ubuntu-22.04
# - macOS-latest
arch:
- x64
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install liclang
- name: Install libclang
run: |
if [ "$RUNNER_OS" = Linux ]; then
sudo apt-get install clang-13 libclang-13-dev
Expand Down
29 changes: 18 additions & 11 deletions .github/workflows/test-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,29 @@ jobs:
matrix:
version:
- '1.10'
- 'nightly'
os:
# - ubuntu-latest
- macOS-latest
# - macOS-latest
- macos-13
arch:
- x64
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install liclang
- name: Install libclang
run: |
if [ "$RUNNER_OS" = Linux ]; then
sudo apt-get install clang-13 libclang-13-dev
else #MacOS
brew install llvm@13
#else #MacOS
# #brew install llvm@13 #llvm@13 no more supported by brew
# wget "https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-13.0.1.tar.gz"
# tar xzf llvmorg-13.0.1.tar.gz
# rm llvmorg-13.0.1.tar.gz
# export CMAKE_INSTALL_MODE=SYMLINK #use symlinks to reduce disk space usage
# cmake -S llvm-project-llvmorg-13.0.1/llvm -B llvm-build -DCMAKE_INSTALL_PREFIX=`pwd`/clang-13 -DLLVM_ENABLE_PROJECTS="clang" -DBUILD_SHARED_LIBS=on -DLLVM_BUILD_LLVM_DYLIB=on -DCMAKE_BUILD_TYPE=Release
# cmake --build llvm-build --verbose -j `sysctl -n hw.logicalcpu`
# cmake --install llvm-build
fi
- uses: julia-actions/setup-julia@latest
with:
Expand All @@ -50,12 +57,12 @@ jobs:
fi
if [ "$RUNNER_OS" = Linux ]; then
cmake -DClang_DIR=/usr/lib/llvm-13/lib/cmake/clang -B build -S .
else #MacOS
#cmake -DClang_DIR=/usr/local/Cellar/llvm@13/13.0.1_2/lib/cmake/clang/ -B build -S .
echo ls /opt/homebrew/opt/llvm@13/lib/cmake/clang
ls /opt/homebrew/opt/llvm@13/lib/cmake/clang
cmake -DClang_DIR=/opt/homebrew/opt/llvm@13/lib/cmake/clang -B build -S .
cmake --build build --verbose -j `nproc`
else
cmake -DBUILD_LLVM=ON -B build -S .
cmake --build build --verbose -j `sysctl -n hw.logicalcpu`
fi
cmake --build build --verbose -j `nproc`
PATH="`pwd`/build:$PATH"
export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)"
cd test && ./runtests.jl
255 changes: 167 additions & 88 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,125 +17,204 @@ FetchContent_Declare(
GIT_REPOSITORY https://github.com/jarro2783/cxxopts.git
GIT_TAG v3.0.0
)

if(BUILD_LLVM) #in this mode llvm and clang codes are downloaded
FetchContent_Declare(llvm
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/llvm
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
URL https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.1/llvm-13.0.1.src.tar.xz
)
FetchContent_GetProperties(llvm)
if(NOT llvm_POPULATED)
FetchContent_Populate(llvm)
endif()

FetchContent_Declare(clang
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/llvm/tools/clang
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
URL https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.1/clang-13.0.1.src.tar.xz
)
FetchContent_GetProperties(clang)
if(NOT clang_POPULATED)
FetchContent_Populate(clang)
endif()
endif()

FetchContent_MakeAvailable(cxxopts)

# CLANG_JLL is used by Binary Builder
# For building the package stand-alone it is not used
if (NOT CLANG_JLL)
project(MyProject)

# Option to enable LLVM/Clang download and build
option(BUILD_LLVM "Download and build LLVM/Clang" OFF)

if(BUILD_LLVM)

function(add_llvm)
set(CMAKE_BUILD_TYPE Release) #applies only for LLVM as defined in the function
set(LLVM_BUILD_LLVM_DYLIB ON)
set(LLVM_BUILD_TOOLS OFF)

string(TOUPPER ${CMAKE_HOST_SYSTEM_PROCESSOR} LLVM_TARGETS_TO_BUILD_)
if(LLVM_TARGETS_TO_BUILD_ STREQUAL "X86_64")
set(LLVM_TARGETS_TO_BUILD_ "X86")
endif()

# Define a couple of LLVM cache variables of LLVM before adding the subdirectory
# in order to choose the default values.
set(LLVM_TARGETS_TO_BUILD ${LLVM_TARGETS_TO_BUILD_} CACHE STRING "Semicolon-separated list of experimental targets to build.")

set(CLANG_RESOURCE_DIR ${CMAKE_INSTALL_PREFIX}/lib/clang/13.0.1 CACHE STRING
"Clang resource directory as returned by clang -print-resource-dir")

add_subdirectory(${llvm_SOURCE_DIR} ${llvm_BINARY_DIR})
endfunction()

add_llvm()

# include_directories(${llvm_SOURCE_DIR}/include
# ${clang_SOURCE_DIR}/include
# ${llvm_BINARY_DIR}/tools/clang/include
# ${llvm_BINARY_DIR}/include)

elseif (NOT CLANG_JLL)

find_package(Clang REQUIRED CONFIG)
find_package(LLVM REQUIRED CONFIG)
include_directories(${CLANG_INCLUDE_DIRS})
find_package(Clang REQUIRED CONFIG)
find_package(LLVM REQUIRED CONFIG)
include_directories(${CLANG_INCLUDE_DIRS})

execute_process(COMMAND "${LLVM_TOOLS_BINARY_DIR}/clang" -print-resource-dir
execute_process(COMMAND "${LLVM_TOOLS_BINARY_DIR}/clang" -print-resource-dir
OUTPUT_VARIABLE CLANG_RESOURCE_DIR_DISCOVERED_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE)

set(CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR_DISCOVERED_PATH}" CACHE
FILEPATH "Clang resource directory as returned by clang -print-resource-dir")

if("${CLANG_RESOURCE_DIR}" STREQUAL "")
message(FATAL_ERROR "CLANG_RESOURCE_DIR needs to be set to the Clang resource directory (see clang -print-resource-directory). This path is used at runtime by the wrapit executable.")
message(FATAL_ERROR "CLANG_RESOURCE_DIR needs to be set to the Clang resource directory (see clang -print-resource-directory). This path is used at runtime by the wrapit executable.")
else()
if(NOT IS_DIRECTORY "${CLANG_RESOURCE_DIR}")
message(WARNING "CLANG_RESOURCE_DIR value, " "${CLANG_RESOURCE_DIR}" ", does not point to an existing directory.")
endif()
if(NOT IS_DIRECTORY "${CLANG_RESOURCE_DIR}")
message(WARNING "CLANG_RESOURCE_DIR value, " "${CLANG_RESOURCE_DIR}" ", does not point to an existing directory.")
endif()
endif()

else() # Using Clang_jll
# find_package(Clang) leads to errors with Clang_jll
# due to inconsitency in the lists of expected and installed files

set(CLANG_PREFIX "" CACHE FILEPATH "Root path of libclang that contains lib/libclang.so.")
if("${CLANG_PREFIX}" STREQUAL "")
find_library(LIBCLANG_PATH_ clang REQUIRED NOCACHE)
get_filename_component(CLANG_PREFIX "${LIBCLANG_PATH_}" DIRECTORY)
get_filename_component(CLANG_PREFIX "${CLANG_PREFIX}" DIRECTORY)
unset(LIBCLANG_PATH_)
message(STATUS "CLANG_PREFIX: ${CLANG_PREFIX}")
endif()
include_directories("${CLANG_PREFIX}/include")

set(CLANG_RESOURCE_DIR "" CACHE STRING
"Clang resource directory as returned by clang -print-resource-dir")
if("${CLANG_RESOURCE_DIR}" STREQUAL "")
message("Searching clang resource directory in " "${CLANG_PREFIX}/lib/clang")
file(GLOB CLANG_RESOURCE_DIR_ "${CLANG_PREFIX}/lib/clang/*/include/stddef.h")
if("${CLANG_RESOURCE_DIR_}" STREQUAL "")
message(FATAL_ERROR "Failed to find Clang resource directory")
else()
list(GET CLANG_RESOURCE_DIR_ 0 CLANG_RESOURCE_DIR)
unset(CLANG_RESOURCE_DIR_)
get_filename_component(CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}" DIRECTORY)
get_filename_component(CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}" DIRECTORY)
message(STATUS "CLANG_RESOURCE_DIR: ${CLANG_RESOURCE_DIR}")
endif()
endif()

set(SHARED_LIBS libclang clang-cpp LLVM)
foreach(shared_lib IN LISTS SHARED_LIBS)
add_library(${shared_lib} SHARED IMPORTED)
set(lib_path "${CLANG_PREFIX}/lib/lib${shared_lib}${CMAKE_SHARED_LIBRARY_SUFFIX}")
string(REPLACE liblib lib lib_path ${lib_path})
set_property(TARGET ${shared_lib} PROPERTY
IMPORTED_LOCATION ${lib_path})
endforeach()

#To prevent 'undefined symbol: _ZN4llvm23EnableABIBreakingChecksE' error:
add_compile_definitions(LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING)

if(NOT ($ENV{target} MATCHES "darwin"))
execute_process(COMMAND /bin/sh -c "nm -D -C ${CLANG_PREFIX}/lib/libclang.so | grep -q abi:cxx11" RESULT_VARIABLE rc)
if(NOT (rc EQUAL 0)) #libclang.so compiled with cxx03 ABI
add_compile_options(-D_GLIBCXX_USE_CXX11_ABI=0)
endif()
endif()
# find_package(Clang) leads to errors with Clang_jll
# due to inconsitency in the lists of expected and installed files

set(CLANG_PREFIX "" CACHE FILEPATH "Root path of libclang that contains lib/libclang.so.")
if("${CLANG_PREFIX}" STREQUAL "")
find_library(LIBCLANG_PATH_ clang REQUIRED NOCACHE)
get_filename_component(CLANG_PREFIX "${LIBCLANG_PATH_}" DIRECTORY)
get_filename_component(CLANG_PREFIX "${CLANG_PREFIX}" DIRECTORY)
unset(LIBCLANG_PATH_)
message(STATUS "CLANG_PREFIX: ${CLANG_PREFIX}")
endif()
include_directories("${CLANG_PREFIX}/include")

set(CLANG_RESOURCE_DIR "" CACHE STRING
"Clang resource directory as returned by clang -print-resource-dir")
if("${CLANG_RESOURCE_DIR}" STREQUAL "")
message("Searching clang resource directory in " "${CLANG_PREFIX}/lib/clang")
file(GLOB CLANG_RESOURCE_DIR_ "${CLANG_PREFIX}/lib/clang/*/include/stddef.h")
if("${CLANG_RESOURCE_DIR_}" STREQUAL "")
message(FATAL_ERROR "Failed to find Clang resource directory")
else()
list(GET CLANG_RESOURCE_DIR_ 0 CLANG_RESOURCE_DIR)
unset(CLANG_RESOURCE_DIR_)
get_filename_component(CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}" DIRECTORY)
get_filename_component(CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}" DIRECTORY)
message(STATUS "CLANG_RESOURCE_DIR: ${CLANG_RESOURCE_DIR}")
endif()
endif()

set(SHARED_LIBS libclang clang-cpp LLVM)
foreach(shared_lib IN LISTS SHARED_LIBS)
set(lib_path "${CLANG_PREFIX}/lib/lib${shared_lib}${CMAKE_SHARED_LIBRARY_SUFFIX}")
string(REPLACE liblib lib lib_path ${lib_path})
if(EXISTS "${lib_path}")
add_library(${shared_lib} SHARED IMPORTED)
else()
set(lib_path "${CLANG_PREFIX}/lib/lib${shared_lib}${CMAKE_STATIC_LIBRARY_SUFFIX}")
string(REPLACE liblib lib lib_path ${lib_path})
if(EXISTS "${lib_path}")
add_library(${shared_lib} STATIC IMPORTED)
else()
message(FATAL_ERROR "${shared_lib} library was not found in ${CLANG_PREFIX}/lib")
endif()
endif()
set_property(TARGET ${shared_lib} PROPERTY
IMPORTED_LOCATION ${lib_path})
endforeach()

#To prevent 'undefined symbol: _ZN4llvm23EnableABIBreakingChecksE' error:
add_compile_definitions(LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING)

if(NOT ($ENV{target} MATCHES "darwin"))
execute_process(COMMAND /bin/sh -c "nm -D -C ${CLANG_PREFIX}/lib/libclang.so | grep -q abi:cxx11" RESULT_VARIABLE rc)
if(NOT (rc EQUAL 0)) #libclang.so compiled with cxx03 ABI
add_compile_options(-D_GLIBCXX_USE_CXX11_ABI=0)
endif()
endif()
endif()


add_custom_target(version
${CMAKE_COMMAND}
-D SRC=${CMAKE_SOURCE_DIR}/src/version.cpp.in
-D DST=${CMAKE_BINARY_DIR}/version.cpp
-D GIT_EXECUTABLE=${GIT_EXECUTABLE}
-P ${CMAKE_SOURCE_DIR}/version.cmake
DEPENDS src/version.cpp.in
)
${CMAKE_COMMAND}
-D SRC=${CMAKE_SOURCE_DIR}/src/version.cpp.in
-D DST=${CMAKE_BINARY_DIR}/version.cpp
-D GIT_EXECUTABLE=${GIT_EXECUTABLE}
-P ${CMAKE_SOURCE_DIR}/version.cmake
DEPENDS src/version.cpp.in
)

# The target 'versions' is used to produce version.cpp
# This dummy custom command is defined to allow
# inclusion of version.cpp dependency to the
# wrapit executable.
add_custom_command(OUTPUT version.cpp
COMMAND true
)
COMMAND true
)

add_executable(wrapit
src/TypeRcd.cpp
src/TypeMapper.cpp
src/utils.cpp
src/cxxwrap_version.cpp
src/uuid_utils.cpp
src/libclang-ext.cpp
src/FunctionWrapper.cpp
src/CodeTree.cpp
src/main.cpp
src/toml.hpp
src/md5sum.cpp
src/FileTimeRestorer.cpp
src/Graph.cpp
version.cpp
src/TypeRcd.cpp
src/TypeMapper.cpp
src/utils.cpp
src/cxxwrap_version.cpp
src/uuid_utils.cpp
src/libclang-ext.cpp
src/FunctionWrapper.cpp
src/CodeTree.cpp
src/main.cpp
src/toml.hpp
src/md5sum.cpp
src/FileTimeRestorer.cpp
src/Graph.cpp
version.cpp
)

add_dependencies(wrapit version)


if(BUILD_LLVM)
message("Set RPATH to: " $ORIGIN/../lib)
set_target_properties(wrapit PROPERTIES INSTALL_RPATH $ORIGIN/../lib)

target_include_directories(wrapit PRIVATE
${llvm_SOURCE_DIR}/include
${clang_SOURCE_DIR}/include
${llvm_BINARY_DIR}/tools/clang/include
${llvm_BINARY_DIR}/include)
endif()

target_link_libraries(wrapit PRIVATE libclang clang-cpp LLVM cxxopts dl
OpenSSL::Crypto)
OpenSSL::Crypto
#- gcc < 9.0 needs std++fs for the std::filesystem support
$<$<AND:$<CXX_COMPILER_ID:GNU>,$<VERSION_LESS:$<CXX_COMPILER_VERSION>,9.0>>:stdc++fs>
)
set_target_properties(wrapit PROPERTIES
CXX_STANDARD 17
OUTPUT_NAME wrapit
POSITION_INDEPENDENT_CODE ON #required for dladdrr on Linux (*)
)
CXX_STANDARD 17
OUTPUT_NAME wrapit
POSITION_INDEPENDENT_CODE ON #required for dladdrr on Linux (*)
)

configure_file(src/config.h.in config.h @ONLY)
include_directories(${CMAKE_CURRENT_BINARY_DIR}) #contains the generated config.h header file
Expand Down

0 comments on commit a28ab4d

Please sign in to comment.