diff --git a/.azure-pipelines/azure-pipelines-linux.yml b/.azure-pipelines/azure-pipelines-linux.yml index 359137d..875d996 100755 --- a/.azure-pipelines/azure-pipelines-linux.yml +++ b/.azure-pipelines/azure-pipelines-linux.yml @@ -12,11 +12,8 @@ jobs: CONFIG: linux_64_ UPLOAD_PACKAGES: 'True' DOCKER_IMAGE: quay.io/condaforge/linux-anvil-cos7-x86_64 - linux_aarch64_: - CONFIG: linux_aarch64_ - UPLOAD_PACKAGES: 'True' - DOCKER_IMAGE: quay.io/condaforge/linux-anvil-aarch64 timeoutInMinutes: 360 + variables: {} steps: # configure qemu binfmt-misc running. This allows us to run docker containers @@ -44,4 +41,4 @@ jobs: env: BINSTAR_TOKEN: $(BINSTAR_TOKEN) FEEDSTOCK_TOKEN: $(FEEDSTOCK_TOKEN) - STAGING_BINSTAR_TOKEN: $(STAGING_BINSTAR_TOKEN) + STAGING_BINSTAR_TOKEN: $(STAGING_BINSTAR_TOKEN) \ No newline at end of file diff --git a/.azure-pipelines/azure-pipelines-osx.yml b/.azure-pipelines/azure-pipelines-osx.yml index f3ff063..ae4e0e7 100755 --- a/.azure-pipelines/azure-pipelines-osx.yml +++ b/.azure-pipelines/azure-pipelines-osx.yml @@ -11,10 +11,8 @@ jobs: osx_64_: CONFIG: osx_64_ UPLOAD_PACKAGES: 'True' - osx_arm64_: - CONFIG: osx_arm64_ - UPLOAD_PACKAGES: 'True' timeoutInMinutes: 360 + variables: {} steps: # TODO: Fast finish on azure pipelines? diff --git a/.ci_support/linux_aarch64_.yaml b/.ci_support/linux_aarch64_.yaml deleted file mode 100644 index 60d0ad4..0000000 --- a/.ci_support/linux_aarch64_.yaml +++ /dev/null @@ -1,26 +0,0 @@ -BUILD: -- aarch64-conda_cos7-linux-gnu -cdt_arch: -- aarch64 -cdt_name: -- cos7 -channel_sources: -- conda-forge -channel_targets: -- conda-forge main -clangdev: -- 17.* -cxx_compiler: -- gxx -cxx_compiler_version: -- '12' -docker_image: -- quay.io/condaforge/linux-anvil-aarch64 -libxml2: -- '2' -target_platform: -- linux-aarch64 -zlib: -- '1.2' -zstd: -- '1.5' diff --git a/.ci_support/migrations/libxml2212.yaml b/.ci_support/migrations/libxml2212.yaml deleted file mode 100644 index fff473a..0000000 --- a/.ci_support/migrations/libxml2212.yaml +++ /dev/null @@ -1,7 +0,0 @@ -__migrator: - build_number: 1 - kind: version - migration_number: 1 -libxml2: -- '2.12' -migrator_ts: 1700445986.2150207 diff --git a/.ci_support/osx_arm64_.yaml b/.ci_support/osx_arm64_.yaml deleted file mode 100644 index 0da34ee..0000000 --- a/.ci_support/osx_arm64_.yaml +++ /dev/null @@ -1,22 +0,0 @@ -MACOSX_DEPLOYMENT_TARGET: -- '11.0' -channel_sources: -- conda-forge -channel_targets: -- conda-forge main -clangdev: -- 17.* -cxx_compiler: -- clang_bootstrap -cxx_compiler_version: -- '16' -libxml2: -- '2' -macos_machine: -- arm64-apple-darwin20.0.0 -target_platform: -- osx-arm64 -zlib: -- '1.2' -zstd: -- '1.5' diff --git a/.scripts/build_steps.sh b/.scripts/build_steps.sh index a4d638b..2f3df6c 100755 --- a/.scripts/build_steps.sh +++ b/.scripts/build_steps.sh @@ -65,7 +65,7 @@ if [[ "${BUILD_WITH_CONDA_DEBUG:-0}" == 1 ]]; then # Drop into an interactive shell /bin/bash else - conda build "${RECIPE_ROOT}" -m "${CI_SUPPORT}/${CONFIG}.yaml" \ + conda-build "${RECIPE_ROOT}" -m "${CI_SUPPORT}/${CONFIG}.yaml" \ --suppress-variables ${EXTRA_CB_OPTIONS:-} \ --clobber-file "${CI_SUPPORT}/clobber_${CONFIG}.yaml" \ --extra-meta flow_run_id="${flow_run_id:-}" remote_url="${remote_url:-}" sha="${sha:-}" diff --git a/.scripts/run_osx_build.sh b/.scripts/run_osx_build.sh index 2879be2..165fa51 100755 --- a/.scripts/run_osx_build.sh +++ b/.scripts/run_osx_build.sh @@ -77,7 +77,7 @@ if [[ "${BUILD_WITH_CONDA_DEBUG:-0}" == 1 ]]; then /bin/bash else - conda build ./recipe -m ./.ci_support/${CONFIG}.yaml \ + conda-build ./recipe -m ./.ci_support/${CONFIG}.yaml \ --suppress-variables ${EXTRA_CB_OPTIONS:-} \ --clobber-file ./.ci_support/clobber_${CONFIG}.yaml \ --extra-meta flow_run_id="$flow_run_id" remote_url="$remote_url" sha="$sha" diff --git a/.scripts/run_win_build.bat b/.scripts/run_win_build.bat index a5871f6..7491838 100755 --- a/.scripts/run_win_build.bat +++ b/.scripts/run_win_build.bat @@ -50,7 +50,7 @@ call :end_group :: Build the recipe echo Building recipe -conda.exe build "recipe" -m .ci_support\%CONFIG%.yaml --suppress-variables %EXTRA_CB_OPTIONS% +conda-build.exe "recipe" -m .ci_support\%CONFIG%.yaml --suppress-variables %EXTRA_CB_OPTIONS% if !errorlevel! neq 0 exit /b !errorlevel! :: Prepare some environment variables for the upload step diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6b346f5..e5306da 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -4,5 +4,5 @@ jobs: - template: ./.azure-pipelines/azure-pipelines-linux.yml - - template: ./.azure-pipelines/azure-pipelines-win.yml - - template: ./.azure-pipelines/azure-pipelines-osx.yml \ No newline at end of file + - template: ./.azure-pipelines/azure-pipelines-osx.yml + - template: ./.azure-pipelines/azure-pipelines-win.yml \ No newline at end of file diff --git a/recipe/CMakeLists.txt b/recipe/CMakeLists.txt new file mode 100644 index 0000000..ecb7f1e --- /dev/null +++ b/recipe/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR) +project(cmake_build_test) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED TRUE) +find_package(CppInterOp REQUIRED) +message(STATUS "CppInterOp library status:") +message(STATUS " config: ${CppInterOp_CONFIG}") +message(STATUS " dir: ${CppInterOp_DIR}") +message(STATUS " version: ${CppInterOp_VERSION}") +message(STATUS " compatible with clang: ${CppInterOp_CLANG_VERSION}") +message(STATUS " libraries: ${CPPINTEROP_LIBRARIES}") +message(STATUS " include path: ${CppInterOp_INCLUDE_DIRS}") +add_executable(cmake_build_test test.cpp) +target_link_libraries(cmake_build_test PRIVATE clangCppInterOp) +add_compile_definitions(cmake_build_test PUBLIC CONDA_PREFIX="${CONDA_PREFIX}") diff --git a/recipe/build.sh b/recipe/build.sh index ad189c2..44b094b 100644 --- a/recipe/build.sh +++ b/recipe/build.sh @@ -4,11 +4,6 @@ set -x # Common settings -export CPU_COUNT="$(nproc --all)" -export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${BUILD_PREFIX}/x86_64-conda-linux-gnu/lib:${BUILD_PREFIX}/lib:${PREFIX}/lib" -sys_include_path=$(LC_ALL=C x86_64-conda-linux-gnu-g++ -O3 -DNDEBUG -xc++ -E -v /dev/null 2>&1 | sed -n -e '/^.include/,${' -e '/^ \/.*++/p' -e '}' | xargs -I$ echo "$" | tr '\n' ':') -export CPLUS_INCLUDE_PATH="${CPLUS_INCLUDE_PATH}:$PWD/include:$sys_include_path:${BUILD_PREFIX}/x86_64-conda-linux-gnu/sysroot/usr/include:${BUILD_PREFIX}/include:${PREFIX}/include" - export clangdev_tag=${clangdev/\.\*/} clangdev1=${clangdev_tag}.0.0 export clangdev_ver=${clangdev1/17\.0\.0/17.0.6} # fix: clang 17.0.0 is removed from releases diff --git a/recipe/meta.yaml b/recipe/meta.yaml index 85f23d3..6ca6150 100644 --- a/recipe/meta.yaml +++ b/recipe/meta.yaml @@ -1,5 +1,5 @@ {% set name = "CppInterOp" %} -{% set build_number = 3 %} +{% set build_number = 4 %} {% set version = "1.2.0" %} {% set revision_tag = "v"+version %} @@ -17,12 +17,20 @@ source: - patches/cppinterop/0002-cmake-CppInterOp-install-fix.patch - patches/cppinterop/0003-Implement-detection-of-resource-and-include-dirs.patch - patches/cppinterop/0004-cmake-config-fix-library-suffix-and-prefix.patch + - patches/cppinterop/0005-Fix-config-for-msvc.patch + - patches/cppinterop/0006-Export-symbols-in-Windows-DLL.patch - path: patches folder: add_patches build: number: {{ build_number }} string: clang{{ (clangdev or "None").split(".")[0] }}_repl_h{{ PKG_HASH }}_{{ build_number }} + error_overlinking: false # FIXME: We should adjust the ignore_run_exports. + ignore_run_exports: + - zstd # [win] + - libxml2 + - backtrace + - libllvm{{ clangdev }} requirements: build: @@ -44,7 +52,7 @@ requirements: - backtrace # [unix and x86] - libxml2 - zlib - - zstd # [not win] + - zstd # [unix] - libcxx {{ cxx_compiler_version }} # [osx] - libstdcxx-ng {{ cxx_compiler_version }} # [linux] run_constrained: @@ -56,9 +64,34 @@ requirements: - libstdcxx-ng >={{ cxx_compiler_version }} # [linux] test: + requires: + - {{ compiler('cxx') }} + - libcxx {{ cxx_compiler_version }} # [osx] + - libstdcxx-ng >={{ cxx_compiler_version }} # [linux] + - cmake + - ninja + files: + - CMakeLists.txt + - test.cpp commands: - test -f $PREFIX/lib/libclangCppInterOp${SHLIB_EXT} # [unix] - if not exist %LIBRARY_BIN%\\clangCppInterOp.dll exit 1 # [win] + # Avoid Bad CPU from cmake when cross-compiling on osx and arm... + - exit 0 # [build_platform != target_platform] + - mkdir -p cmake_build_test && pushd cmake_build_test + - $CXX -xc++ -E -v /dev/null 2>&1 | sed -n -e '/^.include/,${' -e '/^ \/.*/p' -e '}' # [unix] + - cmake -DCMAKE_BUILD_TYPE=Debug -DCONDA_PREFIX="$BUILD_PREFIX" -G "Ninja" .. + - cmake --build . --config Debug -- -v + - ./cmake_build_test $CXX # [unix] + - rm -fr * + - cmake -DCMAKE_BUILD_TYPE=Release -DCONDA_PREFIX="$BUILD_PREFIX" -G "Ninja" .. + - cmake --build . --config Release + - ./cmake_build_test $CXX # [unix] + - rm -fr * + - cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCONDA_PREFIX="$BUILD_PREFIX" -G "Ninja" .. + - cmake --build . --config RelWithDebInfo + - ./cmake_build_test $CXX # [unix] + - popd about: home: https://github.com/compiler-research/CppInterOp diff --git a/recipe/patches/cppinterop/0005-Fix-config-for-msvc.patch b/recipe/patches/cppinterop/0005-Fix-config-for-msvc.patch new file mode 100644 index 0000000..a13c0fb --- /dev/null +++ b/recipe/patches/cppinterop/0005-Fix-config-for-msvc.patch @@ -0,0 +1,88 @@ +From 82478204b3e52f98b3d6622f47ba21fd7c453224 Mon Sep 17 00:00:00 2001 +From: Vassil Vassilev +Date: Mon, 18 Mar 2024 20:09:06 +0000 +Subject: [PATCH] [cmake] Clean up and improve the CppInterOp config for + Windows. + +--- + cmake/CppInterOp/CppInterOpConfig.cmake.in | 41 ++++++++++++++++------ + 1 file changed, 31 insertions(+), 10 deletions(-) + +diff --git a/cmake/CppInterOp/CppInterOpConfig.cmake.in b/cmake/CppInterOp/CppInterOpConfig.cmake.in +index 414c1c0..b2dd5a5 100644 +--- a/cmake/CppInterOp/CppInterOpConfig.cmake.in ++++ b/cmake/CppInterOp/CppInterOpConfig.cmake.in +@@ -9,21 +9,27 @@ get_filename_component(CPPINTEROP_INSTALL_PREFIX "${CPPINTEROP_INSTALL_PREFIX}" + # Determine CMAKE_SHARED_LIBRARY_SUFFIX based on operating system + include(CMakeSystemSpecificInformation) + ++if(MSVC) ++ set(shared_lib_dir bin) ++else() ++ set(shared_lib_dir lib) ++endif() ++ + ### build/install workaround + if (@BUILD_SHARED_LIBS@) +- set(__lib_suffix ${CMAKE_SHARED_LIBRARY_SUFFIX}) +- set(__lib_prefix ${CMAKE_SHARED_LIBRARY_PREFIX}) ++ set(_lib_suffix ${CMAKE_SHARED_LIBRARY_SUFFIX}) ++ set(_lib_prefix ${CMAKE_SHARED_LIBRARY_PREFIX}) + else() +- set(__lib_suffix ${CMAKE_STATIC_LIBRARY_SUFFIX}) +- set(__lib_prefix ${CMAKE_STATIC_LIBRARY_PREFIX}) ++ set(_lib_suffix ${CMAKE_STATIC_LIBRARY_SUFFIX}) ++ set(_lib_prefix ${CMAKE_STATIC_LIBRARY_PREFIX}) + endif() + + if (IS_DIRECTORY "${CPPINTEROP_INSTALL_PREFIX}/include") + set(_include "${CPPINTEROP_INSTALL_PREFIX}/include") +- set(_libs "${CPPINTEROP_INSTALL_PREFIX}/lib/${__lib_prefix}clangCppInterOp${__lib_suffix}") ++ set(_lib "${CPPINTEROP_INSTALL_PREFIX}/${shared_lib_dir}/${_lib_prefix}clangCppInterOp${_lib_suffix}") + else() + set(_include "@CMAKE_CURRENT_SOURCE_DIR@/include") +- set(_libs "@CMAKE_CURRENT_BINARY_DIR@/lib/${__lib_prefix}clangCppInterOp${__lib_suffix}") ++ set(_lib "@CMAKE_CURRENT_BINARY_DIR@/${shared_lib_dir}/${_lib_prefix}clangCppInterOp${_lib_suffix}") + endif() + + ### +@@ -31,7 +37,7 @@ endif() + set(CPPINTEROP_EXPORTED_TARGETS "clangCppInterOp") + set(CPPINTEROP_CMAKE_DIR "${_cmake}") + set(CPPINTEROP_INCLUDE_DIRS "${_include}") +-set(CPPINTEROP_LIBRARIES "${_libs}") ++set(CPPINTEROP_LIBRARIES "${_lib}") + + # Provide all our library targets to users. + if (@BUILD_SHARED_LIBS@) +@@ -39,9 +45,24 @@ if (@BUILD_SHARED_LIBS@) + else() + add_library(clangCppInterOp STATIC IMPORTED) + endif() +-set_property(TARGET clangCppInterOp PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${_include}") +-set_property(TARGET clangCppInterOp PROPERTY IMPORTED_LOCATION "${_libs}") ++set_target_properties(clangCppInterOp PROPERTIES ++ INTERFACE_INCLUDE_DIRECTORIES ${_include} ++ IMPORTED_LOCATION ${_lib} ++ ) ++if (MSVC) ++ if (IS_DIRECTORY "${CPPINTEROP_INSTALL_PREFIX}/include") ++ set(_static_lib "${CPPINTEROP_INSTALL_PREFIX}/lib/${_lib_prefix}clangCppInterOp.lib") ++ else() ++ set(_static_lib "@CMAKE_CURRENT_BINARY_DIR@/lib/${_lib_prefix}clangCppInterOp.lib") ++ endif() ++ ++ set_target_properties(clangCppInterOp PROPERTIES ++ IMPORTED_IMPLIB ${_static_lib} ++ ) ++endif(MSVC) + ++unset(_lib_prefix) ++unset(_lib_suffix) + unset(_cmake) + unset(_include) +-unset(_libs) ++unset(_lib) +-- +2.37.1 (Apple Git-137.1) + diff --git a/recipe/patches/cppinterop/0006-Export-symbols-in-Windows-DLL.patch b/recipe/patches/cppinterop/0006-Export-symbols-in-Windows-DLL.patch new file mode 100644 index 0000000..7805303 --- /dev/null +++ b/recipe/patches/cppinterop/0006-Export-symbols-in-Windows-DLL.patch @@ -0,0 +1,643 @@ +From 310d7c3498442990c9a6980f063e603d5c1c843a Mon Sep 17 00:00:00 2001 +From: Alexander Penev +Date: Wed, 20 Mar 2024 03:02:52 +0000 +Subject: [PATCH] Export symbols in Windows DLL + +--- + include/clang/Interpreter/CppInterOp.h | 270 +++++++++++++------------ + lib/Interpreter/CppInterOp.cpp | 2 +- + 2 files changed, 146 insertions(+), 126 deletions(-) + +diff --git a/include/clang/Interpreter/CppInterOp.h b/include/clang/Interpreter/CppInterOp.h +index 96345ff..4392950 100644 +--- a/include/clang/Interpreter/CppInterOp.h ++++ b/include/clang/Interpreter/CppInterOp.h +@@ -15,6 +15,13 @@ + #include + #include + ++// The cross-platform CPPINTEROP_API macro definition ++#ifdef _WIN32 ++#define CPPINTEROP_API __declspec(dllexport) ++#else ++#define CPPINTEROP_API __attribute__((visibility("default"))) ++#endif ++ + namespace Cpp { + using TCppIndex_t = size_t; + using TCppScope_t = void*; +@@ -29,7 +36,7 @@ namespace Cpp { + /// function, constructor or destructor. + class JitCall { + public: +- friend JitCall MakeFunctionCallable(TCppConstFunction_t); ++ friend CPPINTEROP_API JitCall MakeFunctionCallable(TCppConstFunction_t); + enum Kind : char { + kUnknown = 0, + kGenericCall, +@@ -118,317 +125,325 @@ namespace Cpp { + }; + + ///\returns the version string information of the library. +- std::string GetVersion(); ++ CPPINTEROP_API std::string GetVersion(); + + /// Enables or disables the debugging printouts on stderr. + /// Debugging output can be enabled also by the environment variable + /// CPPINTEROP_EXTRA_INTERPRETER_ARGS. For example, + /// CPPINTEROP_EXTRA_INTERPRETER_ARGS="-mllvm -debug-only=jitcall" to produce + /// only debug output for jitcall events. +- void EnableDebugOutput(bool value = true); ++ CPPINTEROP_API void EnableDebugOutput(bool value = true); + + ///\returns true if the debugging printouts on stderr are enabled. +- bool IsDebugOutputEnabled(); ++ CPPINTEROP_API bool IsDebugOutputEnabled(); + + /// Checks if the given class represents an aggregate type). + ///\returns true if \c scope is an array or a C++ tag (as per C++ + ///[dcl.init.aggr]) \returns true if the scope supports aggregate + /// initialization. +- bool IsAggregate(TCppScope_t scope); ++ CPPINTEROP_API bool IsAggregate(TCppScope_t scope); + + /// Checks if the scope is a namespace or not. +- bool IsNamespace(TCppScope_t scope); ++ CPPINTEROP_API bool IsNamespace(TCppScope_t scope); + + /// Checks if the scope is a class or not. +- bool IsClass(TCppScope_t scope); ++ CPPINTEROP_API bool IsClass(TCppScope_t scope); + + // See TClingClassInfo::IsLoaded + /// Checks if the class definition is present, or not. Performs a + /// template instantiation if necessary. +- bool IsComplete(TCppScope_t scope); ++ CPPINTEROP_API bool IsComplete(TCppScope_t scope); + +- size_t SizeOf(TCppScope_t scope); ++ CPPINTEROP_API size_t SizeOf(TCppScope_t scope); + + /// Checks if it is a "built-in" or a "complex" type. +- bool IsBuiltin(TCppType_t type); ++ CPPINTEROP_API bool IsBuiltin(TCppType_t type); + + /// Checks if it is a templated class. +- bool IsTemplate(TCppScope_t handle); ++ CPPINTEROP_API bool IsTemplate(TCppScope_t handle); + + /// Checks if it is a class template specialization class. +- bool IsTemplateSpecialization(TCppScope_t handle); ++ CPPINTEROP_API bool IsTemplateSpecialization(TCppScope_t handle); + + /// Checks if \c handle introduces a typedef name via \c typedef or \c using. +- bool IsTypedefed(TCppScope_t handle); ++ CPPINTEROP_API bool IsTypedefed(TCppScope_t handle); + +- bool IsAbstract(TCppType_t klass); ++ CPPINTEROP_API bool IsAbstract(TCppType_t klass); + + /// Checks if it is an enum name (EnumDecl represents an enum name). +- bool IsEnumScope(TCppScope_t handle); ++ CPPINTEROP_API bool IsEnumScope(TCppScope_t handle); + + /// Checks if it is an enum's value (EnumConstantDecl represents + /// each enum constant that is defined). +- bool IsEnumConstant(TCppScope_t handle); ++ CPPINTEROP_API bool IsEnumConstant(TCppScope_t handle); + + /// Checks if the passed value is an enum type or not. +- bool IsEnumType(TCppType_t type); ++ CPPINTEROP_API bool IsEnumType(TCppType_t type); + + /// Extracts enum declarations from a specified scope and stores them in + /// vector +- void GetEnums(TCppScope_t scope, std::vector& Result); ++ CPPINTEROP_API void GetEnums(TCppScope_t scope, ++ std::vector& Result); + + /// We assume that smart pointer types define both operator* and + /// operator->. +- bool IsSmartPtrType(TCppType_t type); ++ CPPINTEROP_API bool IsSmartPtrType(TCppType_t type); + + /// For the given "class", get the integer type that the enum + /// represents, so that you can store it properly in your specific + /// language. +- TCppType_t GetIntegerTypeFromEnumScope(TCppScope_t handle); ++ CPPINTEROP_API TCppType_t GetIntegerTypeFromEnumScope(TCppScope_t handle); + + /// For the given "type", this function gets the integer type that the enum + /// represents, so that you can store it properly in your specific + /// language. +- TCppType_t GetIntegerTypeFromEnumType(TCppType_t handle); ++ CPPINTEROP_API TCppType_t GetIntegerTypeFromEnumType(TCppType_t handle); + + /// Gets a list of all the enum constants for an enum. +- std::vector GetEnumConstants(TCppScope_t scope); ++ CPPINTEROP_API std::vector GetEnumConstants(TCppScope_t scope); + + /// Gets the enum name when an enum constant is passed. +- TCppType_t GetEnumConstantType(TCppScope_t scope); ++ CPPINTEROP_API TCppType_t GetEnumConstantType(TCppScope_t scope); + + /// Gets the index value (0,1,2, etcetera) of the enum constant + /// that was passed into this function. +- TCppIndex_t GetEnumConstantValue(TCppScope_t scope); ++ CPPINTEROP_API TCppIndex_t GetEnumConstantValue(TCppScope_t scope); + + /// Gets the size of the "type" that is passed in to this function. +- size_t GetSizeOfType(TCppType_t type); ++ CPPINTEROP_API size_t GetSizeOfType(TCppType_t type); + + /// Checks if the passed value is a variable. +- bool IsVariable(TCppScope_t scope); ++ CPPINTEROP_API bool IsVariable(TCppScope_t scope); + + /// Gets the name of any named decl (a class, + /// namespace, variable, or a function). +- std::string GetName(TCppScope_t klass); ++ CPPINTEROP_API std::string GetName(TCppScope_t klass); + + /// This is similar to GetName() function, but besides + /// the name, it also gets the template arguments. +- std::string GetCompleteName(TCppType_t klass); ++ CPPINTEROP_API std::string GetCompleteName(TCppType_t klass); + + /// Gets the "qualified" name (including the namespace) of any + /// named decl (a class, namespace, variable, or a function). +- std::string GetQualifiedName(TCppType_t klass); ++ CPPINTEROP_API std::string GetQualifiedName(TCppType_t klass); + + /// This is similar to GetQualifiedName() function, but besides + /// the "qualified" name (including the namespace), it also + /// gets the template arguments. +- std::string GetQualifiedCompleteName(TCppType_t klass); ++ CPPINTEROP_API std::string GetQualifiedCompleteName(TCppType_t klass); + + /// Gets the list of namespaces utilized in the supplied scope. +- std::vector GetUsingNamespaces(TCppScope_t scope); ++ CPPINTEROP_API std::vector GetUsingNamespaces(TCppScope_t scope); + + /// Gets the global scope of the whole C++ instance. +- TCppScope_t GetGlobalScope(); ++ CPPINTEROP_API TCppScope_t GetGlobalScope(); + + /// Strips the typedef and returns the underlying class, and if the + /// underlying decl is not a class it returns the input unchanged. +- TCppScope_t GetUnderlyingScope(TCppScope_t scope); ++ CPPINTEROP_API TCppScope_t GetUnderlyingScope(TCppScope_t scope); + + /// Gets the namespace or class (by stripping typedefs) for the name + /// passed as a parameter, and if the parent is not passed, + /// then global scope will be assumed. +- TCppScope_t GetScope(const std::string &name, TCppScope_t parent = 0); ++ CPPINTEROP_API TCppScope_t GetScope(const std::string& name, ++ TCppScope_t parent = 0); + + /// When the namespace is known, then the parent doesn't need + /// to be specified. This will probably be phased-out in + /// future versions of the interop library. +- TCppScope_t GetScopeFromCompleteName(const std::string &name); ++ CPPINTEROP_API TCppScope_t GetScopeFromCompleteName(const std::string& name); + + /// This function performs a lookup within the specified parent, + /// a specific named entity (functions, enums, etcetera). +- TCppScope_t GetNamed(const std::string &name, +- TCppScope_t parent = nullptr); ++ CPPINTEROP_API TCppScope_t GetNamed(const std::string& name, ++ TCppScope_t parent = nullptr); + + /// Gets the parent of the scope that is passed as a parameter. +- TCppScope_t GetParentScope(TCppScope_t scope); ++ CPPINTEROP_API TCppScope_t GetParentScope(TCppScope_t scope); + + /// Gets the scope of the type that is passed as a parameter. +- TCppScope_t GetScopeFromType(TCppType_t type); ++ CPPINTEROP_API TCppScope_t GetScopeFromType(TCppType_t type); + + /// Gets the number of Base Classes for the Derived Class that + /// is passed as a parameter. +- TCppIndex_t GetNumBases(TCppType_t klass); ++ CPPINTEROP_API TCppIndex_t GetNumBases(TCppType_t klass); + + /// Gets a specific Base Class using its index. Typically GetNumBases() + /// is used to get the number of Base Classes, and then that number + /// can be used to iterate through the index value to get each specific + /// base class. +- TCppScope_t GetBaseClass(TCppType_t klass, TCppIndex_t ibase); ++ CPPINTEROP_API CPPINTEROP_API TCppScope_t GetBaseClass(TCppType_t klass, ++ TCppIndex_t ibase); + + /// Checks if the supplied Derived Class is a sub-class of the + /// provided Base Class. +- bool IsSubclass(TCppScope_t derived, TCppScope_t base); ++ CPPINTEROP_API bool IsSubclass(TCppScope_t derived, TCppScope_t base); + + /// Each base has its own offset in a Derived Class. This offset can be + /// used to get to the Base Class fields. +- int64_t GetBaseClassOffset(TCppScope_t derived, TCppScope_t base); ++ CPPINTEROP_API int64_t GetBaseClassOffset(TCppScope_t derived, ++ TCppScope_t base); + + /// Gets a list of all the Methods that are in the Class that is + /// supplied as a parameter. +- std::vector GetClassMethods(TCppScope_t klass); ++ CPPINTEROP_API std::vector GetClassMethods(TCppScope_t klass); + + ///\returns if a class has a default constructor. +- bool HasDefaultConstructor(TCppScope_t scope); ++ CPPINTEROP_API bool HasDefaultConstructor(TCppScope_t scope); + + ///\returns the default constructor of a class, if any. +- TCppFunction_t GetDefaultConstructor(TCppScope_t scope); ++ CPPINTEROP_API TCppFunction_t GetDefaultConstructor(TCppScope_t scope); + + ///\returns the class destructor, if any. +- TCppFunction_t GetDestructor(TCppScope_t scope); ++ CPPINTEROP_API TCppFunction_t GetDestructor(TCppScope_t scope); + + /// Looks up all the functions that have the name that is + /// passed as a parameter in this function. +- std::vector GetFunctionsUsingName( +- TCppScope_t scope, const std::string& name); ++ CPPINTEROP_API std::vector ++ GetFunctionsUsingName(TCppScope_t scope, const std::string& name); + + /// Gets the return type of the provided function. +- TCppType_t GetFunctionReturnType(TCppFunction_t func); ++ CPPINTEROP_API TCppType_t GetFunctionReturnType(TCppFunction_t func); + + /// Gets the number of Arguments for the provided function. +- TCppIndex_t GetFunctionNumArgs(TCppFunction_t func); ++ CPPINTEROP_API TCppIndex_t GetFunctionNumArgs(TCppFunction_t func); + + /// Gets the number of Required Arguments for the provided function. +- TCppIndex_t GetFunctionRequiredArgs(TCppConstFunction_t func); ++ CPPINTEROP_API TCppIndex_t GetFunctionRequiredArgs(TCppConstFunction_t func); + + /// For each Argument of a function, you can get the Argument Type + /// by providing the Argument Index, based on the number of arguments + /// from the GetFunctionNumArgs() function. +- TCppType_t GetFunctionArgType(TCppFunction_t func, TCppIndex_t iarg); ++ CPPINTEROP_API TCppType_t GetFunctionArgType(TCppFunction_t func, ++ TCppIndex_t iarg); + + ///\returns a stringified version of a given function signature in the form: + /// void N::f(int i, double d, long l = 0, char ch = 'a'). +- std::string GetFunctionSignature(TCppFunction_t func); ++ CPPINTEROP_API std::string GetFunctionSignature(TCppFunction_t func); + + ///\returns if a function was marked as \c =delete. +- bool IsFunctionDeleted(TCppConstFunction_t function); ++ CPPINTEROP_API bool IsFunctionDeleted(TCppConstFunction_t function); + +- bool IsTemplatedFunction(TCppFunction_t func); ++ CPPINTEROP_API bool IsTemplatedFunction(TCppFunction_t func); + + /// This function performs a lookup to check if there is a + /// templated function of that type. +- bool ExistsFunctionTemplate(const std::string& name, +- TCppScope_t parent = 0); ++ CPPINTEROP_API bool ExistsFunctionTemplate(const std::string& name, ++ TCppScope_t parent = 0); + + /// Checks if the provided parameter is a method. +- bool IsMethod(TCppConstFunction_t method); ++ CPPINTEROP_API bool IsMethod(TCppConstFunction_t method); + + /// Checks if the provided parameter is a 'Public' method. +- bool IsPublicMethod(TCppFunction_t method); ++ CPPINTEROP_API bool IsPublicMethod(TCppFunction_t method); + + /// Checks if the provided parameter is a 'Protected' method. +- bool IsProtectedMethod(TCppFunction_t method); ++ CPPINTEROP_API bool IsProtectedMethod(TCppFunction_t method); + + /// Checks if the provided parameter is a 'Private' method. +- bool IsPrivateMethod(TCppFunction_t method); ++ CPPINTEROP_API bool IsPrivateMethod(TCppFunction_t method); + + /// Checks if the provided parameter is a Constructor. +- bool IsConstructor(TCppConstFunction_t method); ++ CPPINTEROP_API bool IsConstructor(TCppConstFunction_t method); + + /// Checks if the provided parameter is a Destructor. +- bool IsDestructor(TCppConstFunction_t method); ++ CPPINTEROP_API bool IsDestructor(TCppConstFunction_t method); + + /// Checks if the provided parameter is a 'Static' method. +- bool IsStaticMethod(TCppConstFunction_t method); ++ CPPINTEROP_API bool IsStaticMethod(TCppConstFunction_t method); + + ///\returns the address of the function given its potentially mangled name. +- TCppFuncAddr_t GetFunctionAddress(const char* mangled_name); ++ CPPINTEROP_API TCppFuncAddr_t GetFunctionAddress(const char* mangled_name); + + ///\returns the address of the function given its function declaration. +- TCppFuncAddr_t GetFunctionAddress(TCppFunction_t method); ++ CPPINTEROP_API TCppFuncAddr_t GetFunctionAddress(TCppFunction_t method); + + /// Checks if the provided parameter is a 'Virtual' method. +- bool IsVirtualMethod(TCppFunction_t method); ++ CPPINTEROP_API bool IsVirtualMethod(TCppFunction_t method); + + /// Gets all the Fields/Data Members of a Class. For now, it + /// only gets non-static data members but in a future update, + /// it may support getting static data members as well. +- std::vector GetDatamembers(TCppScope_t scope); ++ CPPINTEROP_API std::vector GetDatamembers(TCppScope_t scope); + + /// This is a Lookup function to be used specifically for data members. +- TCppScope_t LookupDatamember(const std::string& name, TCppScope_t parent); ++ CPPINTEROP_API TCppScope_t LookupDatamember(const std::string& name, ++ TCppScope_t parent); + + /// Gets the type of the variable that is passed as a parameter. +- TCppType_t GetVariableType(TCppScope_t var); ++ CPPINTEROP_API TCppType_t GetVariableType(TCppScope_t var); + + /// Gets the address of the variable, you can use it to get the + /// value stored in the variable. +- intptr_t GetVariableOffset(TCppScope_t var); ++ CPPINTEROP_API intptr_t GetVariableOffset(TCppScope_t var); + + /// Checks if the provided variable is a 'Public' variable. +- bool IsPublicVariable(TCppScope_t var); ++ CPPINTEROP_API bool IsPublicVariable(TCppScope_t var); + + /// Checks if the provided variable is a 'Protected' variable. +- bool IsProtectedVariable(TCppScope_t var); ++ CPPINTEROP_API bool IsProtectedVariable(TCppScope_t var); + + /// Checks if the provided variable is a 'Private' variable. +- bool IsPrivateVariable(TCppScope_t var); ++ CPPINTEROP_API bool IsPrivateVariable(TCppScope_t var); + + /// Checks if the provided variable is a 'Static' variable. +- bool IsStaticVariable(TCppScope_t var); ++ CPPINTEROP_API bool IsStaticVariable(TCppScope_t var); + + /// Checks if the provided variable is a 'Constant' variable. +- bool IsConstVariable(TCppScope_t var); ++ CPPINTEROP_API bool IsConstVariable(TCppScope_t var); + + /// Checks if the provided parameter is a Record (struct). +- bool IsRecordType(TCppType_t type); ++ CPPINTEROP_API bool IsRecordType(TCppType_t type); + + /// Checks if the provided parameter is a Plain Old Data Type (POD). +- bool IsPODType(TCppType_t type); ++ CPPINTEROP_API bool IsPODType(TCppType_t type); + + /// Gets the pure, Underlying Type (as opposed to the Using Type). +- TCppType_t GetUnderlyingType(TCppType_t type); ++ CPPINTEROP_API TCppType_t GetUnderlyingType(TCppType_t type); + + /// Gets the Type (passed as a parameter) as a String value. +- std::string GetTypeAsString(TCppType_t type); ++ CPPINTEROP_API std::string GetTypeAsString(TCppType_t type); + + /// Gets the Canonical Type string from the std string. A canonical type + /// is the type with any typedef names, syntactic sugars or modifiers stripped + /// out of it. +- TCppType_t GetCanonicalType(TCppType_t type); ++ CPPINTEROP_API TCppType_t GetCanonicalType(TCppType_t type); + + /// Used to either get the built-in type of the provided string, or + /// use the name to lookup the actual type. +- TCppType_t GetType(const std::string &type); ++ CPPINTEROP_API TCppType_t GetType(const std::string& type); + + ///\returns the complex of the provided type. +- TCppType_t GetComplexType(TCppType_t element_type); ++ CPPINTEROP_API TCppType_t GetComplexType(TCppType_t element_type); + + /// This will convert a class into its type, so for example, you can + /// use it to declare variables in it. +- TCppType_t GetTypeFromScope(TCppScope_t klass); ++ CPPINTEROP_API TCppType_t GetTypeFromScope(TCppScope_t klass); + + /// Checks if a C++ type derives from another. +- bool IsTypeDerivedFrom(TCppType_t derived, TCppType_t base); ++ CPPINTEROP_API bool IsTypeDerivedFrom(TCppType_t derived, TCppType_t base); + + /// Creates a trampoline function by using the interpreter and returns a + /// uniform interface to call it from compiled code. +- JitCall MakeFunctionCallable(TCppConstFunction_t func); ++ CPPINTEROP_API JitCall MakeFunctionCallable(TCppConstFunction_t func); + + /// Checks if a function declared is of const type or not. +- bool IsConstMethod(TCppFunction_t method); ++ CPPINTEROP_API bool IsConstMethod(TCppFunction_t method); + + ///\returns the default argument value as string. +- std::string GetFunctionArgDefault(TCppFunction_t func, TCppIndex_t param_index); ++ CPPINTEROP_API std::string GetFunctionArgDefault(TCppFunction_t func, ++ TCppIndex_t param_index); + + ///\returns the argument name of function as string. +- std::string GetFunctionArgName(TCppFunction_t func, TCppIndex_t param_index); ++ CPPINTEROP_API std::string GetFunctionArgName(TCppFunction_t func, ++ TCppIndex_t param_index); + + /// Creates an instance of the interpreter we need for the various interop + /// services. + ///\param[in] Args - the list of arguments for interpreter constructor. + ///\param[in] CPPINTEROP_EXTRA_INTERPRETER_ARGS - an env variable, if defined, + /// adds additional arguments to the interpreter. +- extern "C" TInterp_t ++ extern "C" CPPINTEROP_API TInterp_t + CreateInterpreter(const std::vector& Args = {}, + const std::vector& GpuArgs = {}); + +@@ -436,44 +451,47 @@ namespace Cpp { + /// Clang-REPL, etcetera). In practice, the selected interpreter should not + /// matter, since the library will function in the same way. + ///\returns the current interpreter instance, if any. +- TInterp_t GetInterpreter(); ++ CPPINTEROP_API TInterp_t GetInterpreter(); + + /// Adds a Search Path for the Interpreter to get the libraries. +- void AddSearchPath(const char *dir, bool isUser = true, bool prepend = false); ++ CPPINTEROP_API void AddSearchPath(const char* dir, bool isUser = true, ++ bool prepend = false); + + /// Returns the resource-dir path (for headers). +- const char* GetResourceDir(); ++ CPPINTEROP_API const char* GetResourceDir(); + + /// Uses the underlying clang compiler to detect the resource directory. + /// In essence calling clang -print-resource-dir and checks if it ends with + /// a compatible to CppInterOp version. + ///\param[in] ClangBinaryName - the name (or the full path) of the compiler + /// to ask. +- std::string DetectResourceDir(const char* ClangBinaryName = "clang"); ++ CPPINTEROP_API std::string ++ DetectResourceDir(const char* ClangBinaryName = "clang"); + + /// Asks the system compiler for its default include paths. + ///\param[out] Paths - the list of include paths returned by eg. + /// `c++ -xc++ -E -v /dev/null 2>&1` + ///\param[in] CompilerName - the name (or the full path) of the compiler + /// binary file. +- void DetectSystemCompilerIncludePaths(std::vector& Paths, +- const char* CompilerName = "c++"); ++ CPPINTEROP_API void ++ DetectSystemCompilerIncludePaths(std::vector& Paths, ++ const char* CompilerName = "c++"); + + /// Secondary search path for headers, if not found using the + /// GetResourceDir() function. +- void AddIncludePath(const char *dir); ++ CPPINTEROP_API void AddIncludePath(const char* dir); + + /// Only Declares a code snippet in \c code and does not execute it. + ///\returns 0 on success +- int Declare(const char* code, bool silent = false); ++ CPPINTEROP_API int Declare(const char* code, bool silent = false); + + /// Declares and executes a code snippet in \c code. + ///\returns 0 on success +- int Process(const char *code); ++ CPPINTEROP_API int Process(const char* code); + + /// Declares, executes and returns the execution result as a intptr_t. + ///\returns the expression results as a intptr_t. +- intptr_t Evaluate(const char *code, bool *HadError = nullptr); ++ CPPINTEROP_API intptr_t Evaluate(const char* code, bool* HadError = nullptr); + + /// Looks up the library if access is enabled. + ///\returns the path to the library. +@@ -482,18 +500,19 @@ namespace Cpp { + /// Finds \c lib_stem considering the list of search paths and loads it by + /// calling dlopen. + /// \returns true on success. +- bool LoadLibrary(const char* lib_stem, bool lookup = true); ++ CPPINTEROP_API bool LoadLibrary(const char* lib_stem, bool lookup = true); + + /// Finds \c lib_stem considering the list of search paths and unloads it by + /// calling dlclose. + /// function. +- void UnloadLibrary(const char* lib_stem); ++ CPPINTEROP_API void UnloadLibrary(const char* lib_stem); + + /// Scans all libraries on the library search path for a given potentially + /// mangled symbol name. + ///\returns the path to the first library that contains the symbol definition. +- std::string SearchLibrariesForSymbol(const char* mangled_name, +- bool search_system /*true*/); ++ CPPINTEROP_API std::string ++ SearchLibrariesForSymbol(const char* mangled_name, ++ bool search_system /*true*/); + + /// Inserts or replaces a symbol in the JIT with the one provided. This is + /// useful for providing our own implementations of facilities such as printf. +@@ -503,11 +522,11 @@ namespace Cpp { + ///\param[in] address - the new address of the symbol. + /// + ///\returns true on failure. +- bool InsertOrReplaceJitSymbol(const char* linker_mangled_name, +- uint64_t address); ++ CPPINTEROP_API bool InsertOrReplaceJitSymbol(const char* linker_mangled_name, ++ uint64_t address); + + /// Tries to load provided objects in a string format (prettyprint). +- std::string ObjToString(const char *type, void *obj); ++ CPPINTEROP_API std::string ObjToString(const char* type, void* obj); + + struct TemplateArgInfo { + TCppType_t m_Type; +@@ -515,23 +534,24 @@ namespace Cpp { + TemplateArgInfo(TCppScope_t type, const char* integral_value = nullptr) + : m_Type(type), m_IntegralValue(integral_value) {} + }; +- TCppScope_t InstantiateClassTemplate(TCppScope_t tmpl, +- TemplateArgInfo* template_args, +- size_t template_args_size); ++ CPPINTEROP_API TCppScope_t ++ InstantiateClassTemplate(TCppScope_t tmpl, TemplateArgInfo* template_args, ++ size_t template_args_size); + + /// Returns the class template instantiation arguments of \c templ_instance. +- void GetClassTemplateInstantiationArgs(TCppScope_t templ_instance, +- std::vector &args); ++ CPPINTEROP_API void ++ GetClassTemplateInstantiationArgs(TCppScope_t templ_instance, ++ std::vector& args); + + /// Instantiates a function template from a given string representation. This + /// function also does overload resolution. + ///\returns the instantiated function template declaration. +- TCppFunction_t ++ CPPINTEROP_API TCppFunction_t + InstantiateTemplateFunctionFromString(const char* function_template); + +- std::vector GetAllCppNames(TCppScope_t scope); ++ CPPINTEROP_API std::vector GetAllCppNames(TCppScope_t scope); + +- void DumpScope(TCppScope_t scope); ++ CPPINTEROP_API void DumpScope(TCppScope_t scope); + + namespace DimensionValue { + enum : long int { +@@ -540,23 +560,23 @@ namespace Cpp { + } + + /// Gets the size/dimensions of a multi-dimension array. +- std::vector GetDimensions(TCppType_t type); ++ CPPINTEROP_API std::vector GetDimensions(TCppType_t type); + + /// Allocates memory for a given class. +- TCppObject_t Allocate(TCppScope_t scope); ++ CPPINTEROP_API TCppObject_t Allocate(TCppScope_t scope); + + /// Deallocates memory for a given class. +- void Deallocate(TCppScope_t scope, TCppObject_t address); ++ CPPINTEROP_API void Deallocate(TCppScope_t scope, TCppObject_t address); + + /// Creates an object of class \c scope and calls its default constructor. If + /// \c arena is set it uses placement new. +- TCppObject_t Construct(TCppScope_t scope, +- void* arena = nullptr); ++ CPPINTEROP_API TCppObject_t Construct(TCppScope_t scope, ++ void* arena = nullptr); + + /// Calls the destructor of object of type \c type. When withFree is true it + /// calls operator delete/free. +- void Destruct(TCppObject_t This, TCppScope_t type, +- bool withFree = true); ++ CPPINTEROP_API void Destruct(TCppObject_t This, TCppScope_t type, ++ bool withFree = true); + + /// @name Stream Redirection + /// +@@ -571,10 +591,10 @@ namespace Cpp { + + /// Begins recording the given standard stream. + ///\param[fd_kind] - The stream to be captured +- void BeginStdStreamCapture(CaptureStreamKind fd_kind); ++ CPPINTEROP_API void BeginStdStreamCapture(CaptureStreamKind fd_kind); + + /// Ends recording the standard stream and returns the result as a string. +- std::string EndStdStreamCapture(); ++ CPPINTEROP_API std::string EndStdStreamCapture(); + + ///@} + } // end namespace Cpp +diff --git a/lib/Interpreter/CppInterOp.cpp b/lib/Interpreter/CppInterOp.cpp +index 0b93bc8..578f388 100644 +--- a/lib/Interpreter/CppInterOp.cpp ++++ b/lib/Interpreter/CppInterOp.cpp +@@ -2415,7 +2415,7 @@ namespace Cpp { + } // namespace + // End of JitCall Helper Functions + +- JitCall MakeFunctionCallable(TCppConstFunction_t func) { ++ CPPINTEROP_API JitCall MakeFunctionCallable(TCppConstFunction_t func) { + auto* D = (const clang::Decl*)func; + if (!D) + return {}; +-- +2.37.1 (Apple Git-137.1) + diff --git a/recipe/test.cpp b/recipe/test.cpp new file mode 100644 index 0000000..178bb42 --- /dev/null +++ b/recipe/test.cpp @@ -0,0 +1,71 @@ +#include "clang/Interpreter/CppInterOp.h" + +#include +#include +#include +#include + +inline bool file_exists(const std::string& name) { + struct stat buffer; + return (stat (name.c_str(), &buffer) == 0); +} + +inline std::string append_path(const std::string &to, const std::string& what) { +#if defined(WIN32) +# define DIR_SEPARATOR '\\' +#else +# define DIR_SEPARATOR '/' +#endif + return to + DIR_SEPARATOR + what; +} + +using Args = std::vector; + +void* createInterpreter(const char* CxxCompiler, const Args &ExtraArgs = {}) { + Args ClangArgs; + if (std::find(ExtraArgs.begin(), ExtraArgs.end(), "-resource-dir") != ExtraArgs.end()) { + std::string resource_dir = Cpp::DetectResourceDir(); + if (resource_dir == "") + std::cerr << "Failed to detect the resource-dir\n"; + ClangArgs.push_back("-resource-dir"); + ClangArgs.push_back(resource_dir); + } + std::vector CxxSystemIncludes; + // Oddly, conda supports "pseudo cross-compilation" and gives us the compiler + // include paths relative to the compiler binary. Now we need to find out + // where that binary is... + const char* Prefix = CONDA_PREFIX; + Cpp::DetectSystemCompilerIncludePaths(CxxSystemIncludes, CxxCompiler); + for (std::string CxxInclude : CxxSystemIncludes) { + if (!file_exists(CxxInclude)) { + // Try make these paths absolute. + std::string FullPath = append_path(Prefix, CxxInclude); + if (!file_exists(FullPath)) { + std::cerr << "'" << CxxInclude << "'" << " not found, neither is '" + << FullPath << "'\n"; + continue; + } + CxxInclude = FullPath; + } + ClangArgs.push_back("-isystem"); + ClangArgs.push_back(CxxInclude); + } + ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end()); + // FIXME: We should process the kernel input options and conditionally pass + // the gpu args here. + std::vector Args(ClangArgs.size()); + + std::transform(ClangArgs.begin(), ClangArgs.end(), Args.begin(), + [](const std::string &s) -> const char * { return s.data(); }); + + return Cpp::CreateInterpreter(Args/*, {"-cuda"}*/); +} + +int main(int argc, char *argv[]) { + if (argc < 2) + std::cerr << "Not enough arguments. Pass a compiler name.\n"; + + createInterpreter(argv[1], {"-v"}); + + return Cpp::Process("#include "); +}