I am trying to install Catch2 on ubuntu 20.04.
Used instruction from here.
This is what i do:
$ git clone https://github.com/catchorg/Catch2.git
$ cd Catch2
$ cmake -Bbuild -H. -DBUILD_TESTING=OFF
$ sudo cmake --build build/ --target install
Than it saing me that all ok: link for output.
BUT:
When I try to compile the example: // from here
main.cpp
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
#define CATCH_CONFIG_ENABLE_BENCHMARKING
#include <catch2/catch.hpp>
std::uint64_t Fibonacci(std::uint64_t number) {
return number < 2 ? 1 : Fibonacci(number - 1) + Fibonacci(number - 2);
}
TEST_CASE("Fibonacci") {
CHECK(Fibonacci(0) == 1);
// some more asserts..
CHECK(Fibonacci(5) == 8);
// some more asserts..
// now let's benchmark:
BENCHMARK("Fibonacci 20") {
return Fibonacci(20);
};
BENCHMARK("Fibonacci 25") {
return Fibonacci(25);
};
BENCHMARK("Fibonacci 30") {
return Fibonacci(30);
};
BENCHMARK("Fibonacci 35") {
return Fibonacci(35);
};
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(Persistent-world LANGUAGES CXX)
add_executable(${PROJECT_NAME} main.cpp )
find_package(Catch2 REQUIRED)
target_link_libraries(${PROJECT_NAME} Catch2::Catch2)
It output such ERROR: catch2/catch.hpp: No such file or directory
Thanks in advance
The problem is quite simple: clonning catchorg/Catch2 now gets you a v3 branch by default, which works differently. The most important change is that it is no longer single header, and that the catch2/catch.hpp header no longer exists.
You can either switch to the v2 branch before configuring and installing the build, or adapt your code to the changes in v3, starting with this documentation on v2 -> v3 migration.
To get the default main, link against Catch2::Catch2WithMain target.
Admin helped me.
On catch v3. I need:
cmake_minimum_required(VERSION 3.5)
project(Catch2 LANGUAGES CXX)
add_executable(${PROJECT_NAME} main.cpp )
find_package(Catch2)
target_link_libraries(${PROJECT_NAME} Catch2::Catch2WithMain)
If you just link against Catch2::Catch2, you won't get the default main and have to write your own, and your own main needs to invoke the tests. See e.g. that
Than i understand that with main it should looks like:
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
#define CATCH_CONFIG_ENABLE_BENCHMARKING
#include <catch2/catch_all.hpp>
std::uint64_t Fibonacci(std::uint64_t number) {
return number < 2 ? 1 : Fibonacci(number - 1) + Fibonacci(number - 2);
}
TEST_CASE("Fibonacci") {
CHECK(Fibonacci(0) == 1);
// some more asserts..
CHECK(Fibonacci(5) == 8);
// some more asserts..
// now let's benchmark:
BENCHMARK("Fibonacci 20") {
return Fibonacci(20);
};
BENCHMARK("Fibonacci 25") {
return Fibonacci(25);
};
BENCHMARK("Fibonacci 30") {
return Fibonacci(30);
};
BENCHMARK("Fibonacci 35") {
return Fibonacci(35);
};
}
int main( int argc, char* argv[] )
{
Catch::Session session; // There must be exactly one instance
// writing to session.configData() here sets defaults
// this is the preferred way to set them
int returnCode = session.applyCommandLine( argc, argv );
if( returnCode != 0 ) // Indicates a command line error
return returnCode;
// writing to session.configData() or session.Config() here
// overrides command line args
// only do this if you know you need to
int numFailed = session.run();
// numFailed is clamped to 255 as some unices only use the lower 8 bits.
// This clamping has already been applied, so just return it here
// You can also do any post run clean-up here
return numFailed;
}
Related
I'm writing a simple proof of concept app that integrates OpenSSL using NDK. Unfortunately, it gives me undefined reference errors during build.
What I did:
Cross-compiled OpenSSL for Android (x86_64 is shown, and similarly for other ABIs):
openssl-1.1.1q $ ./Configure android-x86_64
openssl-1.1.1q $ make
openssl-1.1.1q $ cp libssl.a <path_to_project_cpp_dir>/libs/x86_64/
openssl-1.1.1q $ cp -r ./include/openssl <path_to_project_cpp_dir>/libs/include/
Added the following CMakeLists.txt into project's cpp dir:
cmake_minimum_required(VERSION 3.18.1)
project("ndk-poc")
add_library(
# Sets the name of the library.
ndk-poc
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
ndk-poc.cpp)
find_library(
# Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that you want CMake to locate.
log)
add_library(libssl STATIC IMPORTED)
set_target_properties(
# Specifies the target library.
libssl
# Specifies the parameter you want to define.
PROPERTIES IMPORTED_LOCATION
# Provides the path to the library you want to import.
${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libssl.a )
include_directories(${CMAKE_SOURCE_DIR}/libs/include/)
target_link_libraries(
# Specifies the target library.
ndk-poc
# Links the target library to the log library
# included in the NDK.
libssl
${log-lib})
And this is my test ndk-poc.cpp:
#include <jni.h>
#include <string>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
extern "C" JNIEXPORT jstring JNICALL
Java_com_techyourchance_android_screens_home_HomeFragment_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
/* Testing OPENSSL prime generation and BigNum. */
BIGNUM *prime1 = NULL;
int bits = 16; /* Number of bits for the generated prime. */
int safe = 0;
prime1 = BN_new();
if (prime1 == NULL) {
printf("Out of memory.\n");
} else if (BN_generate_prime_ex(prime1, bits, safe, NULL, NULL, NULL)) {
printf("Success!\n");
int len;
len = BN_num_bytes(prime1);
unsigned char* buffer;
buffer = static_cast<unsigned char*>(malloc(len));
if (!buffer) {
printf("Out of memory allocating buffer.\n");
} else {
int wlen;
wlen = BN_bn2bin(prime1, buffer);
printf("Wrote %d bytes.\n", wlen);
int i;
for(i=0;i<wlen;++i) {
printf("Byte %d of buffer = %d.\n", i, buffer[i]);
}
free(buffer);
char* st;
st = BN_bn2dec(prime1);
printf("Prime = %s.\n", st);
OPENSSL_free(st);
}
} else {
printf("Error generating prime.\n");
}
std::string result = "Test completed!";
return env->NewStringUTF(result.c_str());
}
Results:
I don't see any errors inside Android Studio, but when I try building the project, all usages of OpenSSL's APIs in my test code result in unresolved reference errors:
...
C:/Users/Vasiliy/projects/ndk-poc/app/src/main/cpp/ndk-poc.cpp:38: error: undefined reference to 'BN_bn2dec'
C:/Users/Vasiliy/projects/ndk-poc/app/src/main/cpp/ndk-poc.cpp:40: error: undefined reference to 'CRYPTO_free'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
What did I miss?
OpenSSL consists of (at least) two libraries: libcrypto which has the general-purpose cryptographic functions; and libssl which is a TLS implementation built on top of libcrypto.
So in your case libcrypto would be the appropriate library to link against.
I would like to be able to create C++ classes and expose them into the V8 JavaScript engine. I'm using the v8pp library to do this, and by following their examples as well as the Google V8 Hello World Script, I have come to this code
main.cpp file
TestClass1.h - whose class I'd like to expose to JavaScript
CMakeList.txt file - so you can see how I've linked V8 if this is important):
// main.cpp
#define V8_COMPRESS_POINTERS
#include <v8.h>
#include <libplatform.h>
#include <v8pp/module.hpp>
#include <v8pp/class.hpp>
#include "src/TestClass1.h"
int main(int argc, char* argv[]) {
v8::V8::InitializeICUDefaultLocation(argv[0]);
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
v8::Isolate *isolate = v8::Isolate::New(create_params);
{
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8pp::module window(isolate);
v8pp::class_<TestClass1> TestClass1_V8(isolate);
TestClass1_V8
.ctor<int, int>()
.set("a", v8pp::property(&TestClass1::getA, &TestClass1::setA))
.set("b", v8pp::property(&TestClass1::getB, &TestClass1::setB))
//.set_static("c", 5, true)
.set("methodA", &TestClass1::testMethod);
window.set("TestClass1", TestClass1_V8);
isolate->GetCurrentContext()->Global()->Set(isolate->GetCurrentContext(), v8pp::to_v8(isolate, "window"), window.new_instance());
v8::Context::Scope context_scope(context);
{
v8::Local<v8::String> source = v8::String::NewFromUtf8Literal(isolate, "(function() {let t = new window.TestClass1(); t.a = 5; return t.a})()");
v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
v8::String::Utf8Value utf8(isolate, result);
printf("%s\n", *utf8);
}
}
return 0;
}
// src/TestClass1.h
#ifndef V8PP_TESTCLASS1_H
#define V8PP_TESTCLASS1_H
class TestClass1 {
friend int main(int argc, char* argv[]);
public:
static int m_c;
TestClass1(int a, int b) {
m_a = a;
m_b = b;
}
int testMethod(int c) {
return m_a + m_b + c;
}
private:
int m_a;
int m_b;
int getA() {
return m_a;
}
void setA(int a) {
m_a = 2 * a;
}
int getB() {
return m_b;
}
void setB(int b) {
m_b = 3 + b;
}
};
#endif //V8PP_TESTCLASS1_H
# CMakeList.txt
cmake_minimum_required(VERSION 3.19)
project(V8PP)
set(CMAKE_CXX_STANDARD 20)
### V8 ### [MANUAL]
set(CMAKE_CXX_FLAGS "/MT")
set(CMAKE_C_FLAGS "/MT")
if(MSVC)
add_compile_options(
$<$<CONFIG:>:/MT> #---------|
$<$<CONFIG:Debug>:/MTd> #---|-- Statically link the runtime libraries
$<$<CONFIG:Release>:/MT> #--|
)
endif()
include_directories(E:/V8/depot_tools/v8/include)
include_directories(E:/V8/depot_tools/v8/include/libplatform)
include_directories(${CMAKE_SOURCE_DIR}/v8pp-master/v8pp-master)
link_directories(E:/V8/depot_tools/v8/out.gn/x64.release/obj/)
link_directories(E:/V8/depot_tools/v8/out.gn/x64.release/obj/third_party)
link_directories(E:/V8/depot_tools/v8/out.gn/x64.release/obj/third_party/icu)
link_libraries(
v8_libbase
v8_libplatform
v8_monolith
icuuc
icui18n
)
link_libraries(winmm.lib)
link_libraries(dbghelp.lib)
link_libraries(shlwapi.lib)
### V8 ###
add_executable(V8PP main.cpp)
I've isolated the error down to the line
isolate->GetCurrentContext()->Global()->Set(isolate->GetCurrentContext(), v8pp::to_v8(isolate, "window"), window.new_instance());
Specifically window.new_instance(). Going into the v8pp source code (file module.hpp), the only line in the method is
return obj_->NewInstance(isolate_->GetCurrentContext()).ToLocalChecked();
I separated out the different statements onto separate lines, and the error is coming from the obj_->NewInstance(), where obj_ is a v8::Local<v8::ObjectTemplate>, created in the initializer list of the constructor of the module object. This function call is part of v8 itself, but I only have access to the header files of v8, so I don't know what has caused the error.
The code builds fine, but when it's run, there isn't a traceback, just:
Process finished with exit code -1073741819 (0xC0000005)
implying a memory access error (maybe to do with pointers?)
Does anyone know how to add a new instance of a v8pp module into the v8 engine without this crash occurring?
Edit
Using:
Windows 10
C++ 20
CMake (on CLion)
MSVC 2019 64-bit
I found the issue: firstly, I had to move the line of code
v8::Context::Scope context_scope(context);
to directly under the line
v8::Local<v8::Context> context = v8::Context::New(isolate);
This did create another error
#
# Fatal error in v8::ToLocalChecked
# Empty MaybeLocal.
#
<unknown>:21: Uncaught argument count does not match function definition
which was because when I called the constructor in JavaScript, I forgot to add the arguments, so changing the JavaScript code to
(function() {let t = new window.TestClass1(); t.a = 5; return t.a;})()
and everything works.
Introduction
I'm doing experimentations using the popular libgit2 written in C.
I'm trying to do a clone but using an un-common way. In order, the git commands:
git init
git remote add origin https://repository.git
git fetch origin
git checkout master
By using git bash and the following commands, I can get an existing repository with all its history.
Question
Now, let's see my current C++ implementation. The following code is trying to copy the behaviour of the previous written git commands.
#define url "https://repository.git"
#define path "./"
#define user "user"
#define pass "pass"
/** credential callback **/
int credentials(git_cred **cred, const char *, const char *, unsigned int, void *) {
return git_cred_userpass_plaintext_new(cred, user, pass);
}
class Git {
public:
Git() {
git_libgit2_init();
}
~Git() {
git_repository_free(repository);
git_libgit2_shutdown();
}
void update() {
init();
fetch();
checkout();
}
private:
void init() {
assertSuccess(git_repository_init(&repository, path, GIT_CVAR_FALSE));
git_remote *remote = nullptr;
git_remote_callbacks options = GIT_REMOTE_CALLBACKS_INIT;
assertSuccess(git_remote_create(&remote, repository, "origin", url));
options.credentials = credentials;
git_remote_connect(remote, GIT_DIRECTION_FETCH, &options, nullptr, nullptr);
}
void fetch() {
git_remote* remote = nullptr;
assertSuccess(git_remote_lookup(&remote, repository, "origin"));
git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
options.callbacks.credentials = credentials;
assertSuccess(git_remote_fetch(remote, nullptr, &options, nullptr));
}
void checkout() {
git_checkout_options options = GIT_CHECKOUT_OPTIONS_INIT;
options.checkout_strategy = GIT_CHECKOUT_FORCE;
assertSuccess(git_checkout_head(repository, &options));
assertSuccess(git_checkout_index(repository, nullptr, &options));
assertSuccess(git_repository_set_head(repository, "refs/heads/master"));
git_object *treeish = nullptr;
assertSuccess(git_revparse_single(&treeish, repository, "master"));
assertSuccess(git_checkout_tree(repository, treeish, &options));
}
void assertSuccess(int error) {
if (!error) return;
const git_error *e = giterr_last();
std::cout << "code: " << e->klass << " error: " << e->message << std::endl;
exit(1);
}
private:
git_repository *repository = nullptr;
};
int main() {
Git git;
git.update();
return 0;
}
Obviously, this does not work. Running this program (calling Git().update()), I'm getting the following error during the checkout step:
code: 4 error: reference 'refs/heads/master' not found
The git repository has been created and I can see the remote origin that has been set successfully though git bash. I can do a manual git checkout master from git bash so I guess my current implementation of checkout is a failure.
Could someone highlight me about this error? I couldn't find enough resources nor support on all found example on internet.
EDIT
Since testing my code might help, let me give my CMakeLists.txt for compile libgit2. (source code https://github.com/libgit2/libgit2)
cmake_minimum_required(VERSION 3.13)
project(test)
include_directories(libgit/include)
LINK_DIRECTORIES(${LIBSSH2_LIBRARY_DIRS})
add_subdirectory(libgit)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_BUILD_TYPE Release)
add_executable(test src/Git.h)
target_link_libraries(test git2)
The missing link is that, since you're building a repository from scratch, your repository is still unborn (ie, its HEAD points to a non-existent refs/heads/master ref). On top of that, checkout's only concern in libgit2-land is about bringing out files from the ODB, it doesn't write or update references.
Hence, you are missing the step where git checkout uses (in all likelihood) git update-ref to make master point to origin/master's OID, and you can do that via git_reference_create and friends.
Something like the following (brain-compiled):
static int setup_tracking_branch(char *branch_name, git_reference *upstream)
{
git_reference *tracking;
git_oid up_oid = git_reference_target_peel(upstream);
char *ui_name;
#if 0
/* should be constructed from `upstream`. IIRC there are some
* git_reference accessors that can help
* (eg. `refs/remotes/origin/heads/master` is `origin/master`).
*/
#else
ui_name = "origin/master";
#endif
if (git_reference_create_matching(&tracking,
git_reference_owner(upstream),
branch_name, up_oid, 0, NULL, "branch: created from %s", ui_name) < 0 ||
git_branch_set_upstream(tracking, git_reference_name(upstream)) < 0) {
printf("failed to create remote-tracking branch\n");
return -1;
}
cleanup:
git_reference_free(tracking);
return 0;
}
This takes the name you want the new branch to be (-b), and the remote branch to track (-t), though it is clearly not a complete reimplementation, or even correct, so YMMV.
OS:x64 win7 sp1 with vs2017
I use vcpkg to install gtest, and then try to test it.
I create a dir and it has two files:
//main.cpp
#include <gtest/gtest.h>
int add(int a, int b){
return a + b;
}
TEST(addTest, add){
EXPECT_EQ(1, add(2, -1));
EXPECT_EQ(5, add(2, 3));
}
int main(int argc, char *argv[]){
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TEST();
}
# CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(test)
find_package(GTest REQUIRED)
add_executable(main main.cpp)
target_link_libraries(main gtest)
Then I use cmake .. "-DCMAKE_TOOLCHAIN_FILE=C:/src/vcpkg/scripts/buildsystems/vcpkg.cmake" and cmake --build ., and here is the log:
C:\src\cmake-test\main.cpp(17): error C3861: “RUN_ALL_TEST”: 找不到标识符(can't find the identifier) [C:\src\cmake-test\build\main.vcxproj]
已完成生成项目“C:\src\cmake-test\build\main.vcxproj”(默认目标)的操作 - 失败。
已完成生成项目“C:\src\cmake-test\build\ALL_BUILD.vcxproj”(默认目标)的操作 - 失败。
生成失败。
“C:\src\cmake-test\build\ALL_BUILD.vcxproj”(默认目标) (1) ->“C:\src\cmake-test\build\main.vcxproj”(默认目标) (3) ->(ClCompile 目标) -> C:\src\cmake-test\main.cpp(17): error C3861: “RUN_ALL_TEST”: 找不到标识符(can't find the identifier) [C:\src\cmake-test\build\main.vcxproj]
0 个警告(warnings)
1 个错误(errors)
已用时间 00:00:01.15
It seems that "RUN_ALL_TEST" is not be defined.
So how to solve the problem?
After successfully compiling a Python/C binding with SIP I wanted to do the same thing with Python/C++. For some reason this doesn't work.
Here's the files:
fib.cpp
#include "fib.h"
int fib1(int n)
{
if (n <= 0) {
return 0;
} else if (n <= 2) {
return 1;
} else {
return fib1(n-1) + fib1(n-2);
}
}
fib.h
int fib1(int n);
fib.sip
%Module fib
%Include fib.h
I run the following command to build the intermediate files:
sip -c . fib.sip
So far everything works.
Now I want to build the .pyd file using distutils.
setup.py
from distutils.core import setup, Extension
import sipdistutils
setup(
name = 'fib',
versione = '1.0',
ext_modules=[
Extension("fib", ["fib.sip", "fib.cpp"]),
],
cmdclass = {'build_ext': sipdistutils.build_ext}
)
I run the following command:
python setup.py build
This fails with the following error:
build\temp.win32-2.7\Release\sipfibcmodule.cpp:29:29: error: 'fib1' was not declared in this scope
error: command 'gcc' failed with exit status 1
What could the problem be? Shouldn't c++ be used as a compiler instead of gcc, by the way?
Any help appreciated!
Kind regards
David
I've found a solution that is good enough: namespaces. Next time I'll read the documentation better. I should also mention that a solution with a Fibonacci class could solve the problem, but I didn't find that to be satisfying.
Below the content of the files can be found.
fib.cpp
#include "fib.h"
namespace test
{
int fib1(int n)
{
if (n <= 0) {
return 0;
} else if (n <= 2) {
return 1;
} else {
return fib1(n-1) + fib1(n-2);
}
}
}
fib.h
namespace test
{
int fib1(int n);
}
fib.sip
%Module fib
namespace test {
%TypeHeaderCode
#include "fib.h"
%End
int fib1(int n);
};
setup.py - nothing was changed
Exactly the same commands as mentioned before were used.