CMake adds -Dlibname_EXPORTS compile definition - cmake

CMake adds the following compile definition to all source code files automatically when simply compiling a target:
-Dlibname_EXPORTS
Why is this done and how can I disable it?

cmake add <libname>_EXPORTS macros only for shared libraries. It's useful when exporting API's in Windows DLL.
#if defined(_WINDOWS) && defined(testlib_EXPORTS)
# define API_DLL extern "C" __declspec(dllexport)
#else
# define API_DLL
#endif
API_DLL void foo();
It could be disabled by setting the DEFINE_SYMBOL property of target to empty.
# disable the <libname>_EXPORTS
set_target_properties(sharedlib
PROPERTIES
DEFINE_SYMBOL ""
)
Reference
http://www.cmake.org/cmake/help/v3.0/prop_tgt/DEFINE_SYMBOL.html

Related

How can Poplar codelets include code from other header files?

Is it possible for codelets to reference code in other files, like header files?
If I have a codelet file
//FileA.cpp
#include "FileB.h"
class SomeCustomVertex : public Vertex {
public:
bool compute() {
int a = SomeConstantDefinedInFileB;
}
...
}
and some other "codelet" file
//FileB.h
const int SomeConstantDefineInFileB = 42;
and in the host graph program:
graph.addCodelets({"codelets/FileA.cpp", "codelets/FileB.h"});
I get a compile error from popc:
fatal error: 'FileB.h' file not found
#include "FileB.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
terminate called after throwing an instance of 'poplar::graph_program_compilation_error'
what(): Codelet compilation failed (see compiler output for details)
I figured this out.
Graph::addCodelets has a parameter StringRef compileFlags = "", which you can use to inject compiler options.
popc --help shows an option
-I arg Add directory to include search path
So when I use graph.addCodelets({"codelets/FileA.cpp"}, "-I codelets"); in the host program, and have my codelets in 'codelets' subdirectory, this works. No need to explicitly list the ".h" files in the arguments.
Incidentally, also a good way to ensure compiler optimisation (-O3) for the custom codelets.

Error when compiling a program that uses Assimp with MinGW in CLion

I'm trying to compile a program in CLion that uses the Assimp library using the MinGW compiler. When building the project it gets up to 77% and gives the following error on the file "SMDLoader.cpp.obj":
C:\Dev\AssimpTest\cmake-build-debug\_deps\assimp-src\code\SMDLoader.cpp: In member function 'void Assimp::SMDImporter::GetAnimationFileList(const string&, Assimp::IOSystem*, std::vector<std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)':
C:\Dev\AssimpTest\cmake-build-debug\_deps\assimp-src\code\SMDLoader.cpp:579:47: error: 'strtok_s' was not declared in this scope
tok1 = strtok_s(&buf[0], "\r\n", &context1);
^
_deps\assimp-build\code\CMakeFiles\assimp.dir\build.make:2246: recipe for target '_deps/assimp-build/code/CMakeFiles/assimp.dir/SMDLoader.cpp.obj' failed
This is the CMakeLists.txt file i'm using:
cmake_minimum_required(VERSION 3.13)
project(AssimpTest)
set(CMAKE_CXX_STANDARD 11)
find_package(assimp 4.1.0 QUIET)
if (NOT assimp_FOUND)
include(FetchContent)
FetchContent_Declare(
assimp
URL https://github.com/assimp/assimp/archive/master.tar.gz
)
FetchContent_GetProperties(raylib)
if (NOT assimp_POPULATED)
set(FETCHCONTENT_QUIET NO)
FetchContent_Populate(assimp)
set(CMAKE_BUILD_TYPE release CACHE STRING "" FORCE)
set(ASSIMP_BUILD_TESTS OFF CACHE BOOL "" FORCE)
add_subdirectory(${assimp_SOURCE_DIR} ${assimp_BINARY_DIR})
endif()
endif()
add_executable(AssimpTest main.cpp)
target_link_libraries(${PROJECT_NAME} assimp)
Here's the main file i'm trying to compile, just in case:
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
int main() {
Assimp::Importer importer;
const char* pFile = R"(C:\Dev\raycast\models\teapot.fbx)";
const aiScene* scene = importer.ReadFile( pFile,
aiProcess_CalcTangentSpace |
aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices |
aiProcess_SortByPType);
if( !scene)
{
printf(importer.GetErrorString());
return -1;
}
printf("Num meshes: %i", scene->mNumMeshes);
return 0;
}
The main reason i'm trying to use Assimp is to import .fbx models into my program, so if there is any way to optimize all of this setup just for that, that would be really helpful!
The information i found about the usage of this library with MinGW on the internet was really scarce.
Anyway thanks for help in advance.
If you don't need the SMD loader, you can simply disable it. Go to File -> Settings -> Build, Execution, Deployment -> CMake and insert "-DASSIMP_BUILD_SMD_LOADER=NO" (without " ") into CMake options
GCC does not implement the _s functions. The solution is to change the #indef condition at the top of the SMDloader.cpp to check agains _MSC_VER instead of _WIN32:
#ifndef _MSC_VER
#define strtok_s strtok_r
#endif
Which mingw- and assimp-version do you use? Mingw is part of the CI-buildchain we are using to test the assimp-code and this issue shall not occur anymore. So if this issue is on our current master we need to fix it.
And which kind of information do you miss when using mingw? I will try to optimize this.
Thanks!

Building LLVM pass out of source - undefined symbols

I'm attempting to build an LLVM pass using the instructions here and link it against the copy of LLVM installed by Julia. The pass is currently being compiled successfully, but cmake fails on linking with undefined symbol errors.
[ 50%] Building CXX object VectorizePass/CMakeFiles/VectorizePass.dir/VectorizePass.cpp.o
[100%] Linking CXX shared module libVectorizePass.so
Undefined symbols for architecture x86_64:
"llvm::raw_ostream::write_escaped(llvm::StringRef, bool)", referenced from:
(anonymous namespace)::Hello::runOnFunction(llvm::Function&) in VectorizePass.cpp.o
"llvm::raw_ostream::write(char const*, unsigned long)", referenced from:
llvm::raw_ostream::operator<<(llvm::StringRef) in VectorizePass.cpp.o
There are dozens of undefined symbol errors followed by
"vtable for llvm::Pass", referenced from:
llvm::Pass::Pass(llvm::PassKind, char&) in VectorizePass.cpp.o
NOTE: a missing vtable usually means the first non-inline virtual
member function has no definition.
VectorizePass.cpp
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
struct Hello : public FunctionPass {
static char ID;
Hello() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
errs() << "Hello: ";
errs().write_escaped(F.getName()) << "\n";
return false;
}
};
}
char Hello::ID = 0;
static RegisterPass<Hello> X("Hello", "My Hello World Pass", false, false);
This is exactly as it is in the tutorial.
CMakeLists.txt (1)
add_library(VectorizePass MODULE VectorizePass.cpp)
SET(CMAKE_CXX_FLAGS "-std=c++11 -Wall -fno-rtti -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS -fPIC")
CMakeLists.txt (2)
project(VectorizePass)
set(LLVM_DIR "/Users/user/julia5/deps/build/llvm-3.7.1/build_Release")
set(LLVM_TOOLS_BINARY_DIR "/Users/user/julia5/deps/build/llvm-3.7.1/build_Release/Release/bin")
include_directories(${LLVM_INCLUDE_DIRS})
include_directories("/Users/user/julia5/deps/build/llvm-3.7.1/build_Release/include")
include_directories("/Users/user/julia5/deps/srccache/llvm-3.7.1/include")
link_directories("/Users/user/julia5/deps/build/llvm-3.7.1/build_Release/Release/lib")
link_directories("/Users/user/julia5/deps/build/llvm-3.7.1/build_Release/lib")
link_directories(${LLVM_LINK_DIRS})
add_definitions(${LLVM_DEFINITIONS})
add_subdirectory(VectorizePass)
Clearly, for some reason CMake isn't finding the appropriate object files even though they are in the directories that I have in the link_directories statements. What am I missing? I'm fairly new to CMake so it may be something obvious.
I've attempted to include(AddLLVM) as suggested here but CMake reports that it cannot find AddLLVM. This Stack post also suggests using a regular Makefile but that does not work when compiling out-of-source passes as all the paths in the regular LLVM Makefile.common/Makefile.config are relative and don't work at all.
Have you read this? You need to use add_llvm_loadable_module() macro to define target for your pass.

Calling a dll from fortran

I am aiming at calling a dll file from a fortran compiler. I am doing all this in windows using the mingw compiler.
The dll was created using a g++ compiler
The code for which I am trying to create a dll
// example_dll.cpp
#include <stdio.h>
#include "example_dll.h"
__stdcall void hello()
{
printf("Hello");
}
command entered in the command prompt
g++ -c -DBUILDING_EXAMPLE_DLL example_dll.cpp
g++ -shared -o example_dll.dll example_dll.o -Wl,--out-implib,libexample_dll.a
The above two commands creates the dll file.
The job now is to create a fortran script to compile the dll file previously created.
For this purpose I am looking forward to create a fortran file capable of linking to the dll previously created.
Any help will be appreciated.
Thanks,
Adarsh
Later I tried some of the possibilities. My updated files are as follows
C file for which the DLL is created is as follows
// example_dll.c
#include <stdio.h>
#include "example_dll.h"
EXPORT void tstfunc (void)
{
printf("Hello\n");
}
EXPORT int Double11(int x)
{
printf("From the Double11\n");
printf("%d\n",x);
return x;
}
.h file used to create the DLL is as follows
// example_dll.h
#ifdef EXAMPLE_DLL_H
// the dll exports
#define EXPORT __declspec(dllexport)
#else
// the exe imports
#define EXPORT __declspec(dllimport)
#endif
// function to be imported/exported
EXPORT void tstfunc (void);
EXPORT int Double11(int x);
Fortran file used to link the dll is as follows
! fortcall.f90
program ForCall
IMPLICIT NONE
integer :: sum
integer :: inte3
INTERFACE
SUBROUTINE write() BIND(C,NAME='tstfunc')
END SUBROUTINE write
END INTERFACE
INTERFACE
SUBROUTINE get_integer(inte,inte2) BIND(C,NAME='Double11')
USE ISO_C_BINDING
IMPLICIT NONE
INTEGER (C_INT), VALUE :: inte
INTEGER (C_INT), INTENT(OUT) :: inte2
END SUBROUTINE get_integer
END INTERFACE
CALL write
CALL get_integer(1,inte3)
print*,"the output is",inte3
END PROGRAM ForCall
After entering the following directive in the command prompt
gfortran -o dll_foo_test fortcall.f90 -L. example_dll.dll
The output will be as follows
Hello
From the Double11
1
the output is -2
At this point something is not right. The code is capable of passing a value from FORTRAN to the DLL, whereas the code is not returning the right value from the dll. Some junk value of -2 is being displayed instead of 1.
I would like to fix that part in the code.

How to create dll using gcc compiler/Mingw for visual basic?

How to create dll using gcc compiler/Mingw for visual basic?
The following is how I was able to get MinGW to build a DLL to be used in Excel 2003 VBA.
fooBar.cpp
int __stdcall Foo(int x)
{
return x * x;
}
double __stdcall Bar(double x)
{
return x * x;
}
1) Start MinGW shell and create a directory called fooBar .
Close the Excel Workbook (if open).
mkdir -p fooBar
cd fooBar
rm *.a *.dll *.def
2) Compile and generate a .def file - Note: this dll will not work because it has mangled symbols.
gcc -shared -o fooBar.dll fooBar.cpp -Wl,--output-def,fooBar.def,--out-implib,libfooBardll.a
The generated fooBar.def will look something like:
EXPORTS
_Z3Bard#8 #1
_Z3Fooi#4 #2
3) Modify the generated fooBar.def file by adding clean symbol aliases for the generated symbols. fooBar.def should now look something like:
EXPORTS
_Z3Bard#8 #1
_Z3Fooi#4 #2
Bar = _Z3Bard#8
Foo = _Z3Fooi#4
4) Cleaup again (except for the modified fooBar.def)
rm *.a *.dll
5) Compile with .def file with clean symbol aliases for the generated symbols.
gcc -shared -o fooBar.dll fooBar.cpp fooBar.def -Wl,--out-implib,libfooBar_dll.a
6) Open Excel and add the following VBA code (make sure to use the proper path, doubt it will have mmorris in it):
Private Declare Function Foo Lib _
"C:\MinGW\msys\1.0\home\mmorris\fooBar\fooBar.dll" _
(ByVal x As Long) As Long
Private Declare Function Bar Lib _
"C:\MinGW\msys\1.0\home\mmorris\fooBar\fooBar.dll" _
(ByVal x As Double) As Double
7) If you want to call the functions from an Excel Workbook, in a cell type =Foo(5) or =Bar(5)
First some DLL-iquette:
All exported function should have C linkage.
All C++-exceptions thrown inside the DLL should be catched inside the dll.
Why? Because there is no standard C++ ABI on Windows.
Also use __declspec(dllexport) on functions that should be exported
Now how to make the DLL without needing any DEF file
fooBar.cpp
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) int __stdcall square_int(int x) //I prefer manual mangling in this case to support static polymorphism
{
return x * x;
}
__declspec(dllexport) double __stdcall square_double(double x)
{
return x * x;
}
#ifdef __cplusplus
}
#endif
compile using
gcc fooBar.cpp -shared -Wl,--kill-at -o fooBar.dll
Now you should be able to call square_xxx as in mmorris answer. His solution probably works though.
This: http://www.mingw.org/wiki/DLL might be useful to you.
VB (all versions) prefers the pascal calling convention.
Declare your external functions with WINAPI and export them in your .def file.