I am building unit test software for my library. I am using Catch2 Testing Framework Version 3.1.0
When I am trying to include the catch_all file in my aml_vector3_test.cpp but it is giving file not found error.
#include <catch2/catch_all.hpp> //Error in this line
#include "aml.h"
I had referred the link for integration of vcpkg with my cmake prokect
I have tried both set (CMAKE_TOOLCHAIN_FILE "D:/vcpkg/scripts/buildsystems/vcpkg.cmake") and include ("D:/vcpkg/scripts/buildsystems/vcpkg.cmake") in both my global CMake file and test project cmake file but it still didn't help. I tried all permutation and combination with this.
Kindly note I have zero exposure to cmake and have no idea what I am doing.
Project Structure
aml
|--CMakeLists.txt (CMake File 1)
|--CMakeSettings.json
|--aml
| |--CMakeLists.txt (CMake File 2)
| |--aml.h
| |--aml_vector3.cpp
| |--aml_vector3.h
|--example
| |--CMakeLists.txt (CMake File 3)
| |--main.cpp
|--test
| |--CMakeLists.txt (CMake File 4)
| |--main.cpp
| |--aml_vector3_test.cpp
CMake1 (Global CMake)
# CMakeList.txt : Top-level CMake project file, do global configuration
# and include sub-projects here.
#
cmake_minimum_required (VERSION 3.8)
set (CMAKE_C_STANDARD 17)
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_TOOLCHAIN_FILE "D:/vcpkg/scripts/buildsystems/vcpkg.cmake")
project ("AttitudeMathLibrary")
# Include sub-projects.
add_subdirectory ("aml")
add_subdirectory ("test")
add_subdirectory ("example")
#enable_testing()
#add_test(test_all aml_vector3_test/aml_test)
Cmake2 (Main Library CMake)
# CMakeList.txt : CMake project for aml_vector3, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)
project(aml)
# Add source to this project's executable.
# add_executable (aml_vector3 "aml_vector3.cpp" "aml_vector3.h" "aml.h")
# target_sources ("aml_vector3.cpp" "aml_vector3.h" "aml.h")
set (SRC_CPP_AML "aml_vector3.cpp" "aml_vector3.h" "aml.h")
# TODO: Add tests and install targets if needed.
add_library (${PROJECT_NAME} STATIC ${SRC_CPP_AML})
target_include_directories (${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR})
CMake3 (Example Project CMake)
# CMakeList.txt : CMake project for aml_vector3, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)
project (aml_example)
# Add source to this project's executable.
add_executable (${PROJECT_NAME} "main.cpp")
# TODO: Add tests and install targets if needed.
target_link_libraries(${PROJECT_NAME} aml)
install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_BINARY_DIR}/bin)
CMake 4 (Unit Test Camke)
# CMakeList.txt : CMake project for aml_vector3, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)
#set (CMAKE_TOOLCHAIN_FILE "D:/vcpkg/scripts/buildsystems/vcpkg.cmake")
include ("D:/vcpkg/scripts/buildsystems/vcpkg.cmake")
project (aml_test)
find_package(catch2 CONFIG REQUIRED)
# Add source to this project's executable.
add_executable (${PROJECT_NAME} "main.cpp" "aml_vector3_test.cpp")
include_directories(${CATCH2_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} aml)
target_link_libraries(${PROJECT_NAME} catch2)
# TODO: Add tests and install targets if needed.
CMakeSettings.json
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"variables": [
{
"name": "CMAKE_BUILD_TYPE",
"value": "Debug",
"type": "STRING"
},
{
"name": "CMAKE_INSTALL_PREFIX",
"value": "C:/Users/darksorrow/source/repos/aml_vector3/out/install/x64-Debug",
"type": "PATH"
},
{
"name": "CMAKE_MAKE_PROGRAM",
"value": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe",
"type": "FILEPATH"
},
{
"name": "CMAKE_TOOLCHAIN_FILE",
"value": "D:/vcpkg/scripts/buildsystems/vcpkg.cmake"
}
]
}
]
}
message ("CATCH2_INCLUDE_DIRS : ${CATCH2_INCLUDE_DIRS}")
prints
[CMake] CATCH2_INCLUDE_DIRS : D:/vcpkg/installed/x64-windows/include
Other Codes:
aml.h
#pragma once
// Helper file - Imports all Attitude Math Library Files in a single file.
// This is a convenience file for the user
#include "aml_vector3.h"
aml_vector.h
#include <iostream>
namespace aml
{
class Vector3
{
public:
union
{
double data[3];
struct
{
double x, y, z;
};
};
//Constructors
Vector3();
Vector3(double value);
Vector3(double x, double y, double z);
Vector3(double data[3]);
//Operator Assignment (Vector)
Vector3& operator+=(const Vector3& rhs);
Vector3& operator-=(const Vector3& rhs);
Vector3& operator*=(const Vector3& rhs);
Vector3& operator/=(const Vector3& rhs);
//Operator Assignment (Scalar)
Vector3& operator+=(double s);
Vector3& operator-=(double s);
Vector3& operator*=(double s);
Vector3& operator/=(double s);
};
}
aml_vector.cpp
#include <cmath>
#include "aml_vector3.h"
namespace aml
{
Vector3::Vector3() : x(0.0), y(0.0), z(0.0)
{
}
Vector3::Vector3(double value) : x(value), y(value), z(value)
{
}
Vector3::Vector3(double x, double y, double z) : x(x), y(y), z(z)
{
}
Vector3::Vector3(double data[3]) : x(data[0]), y(data[1]), z(data[2])
{
}
Vector3& Vector3::operator+=(const Vector3& rhs)
{
this->x += rhs.x;
this->y += rhs.y;
this->z += rhs.z;
return *this;
}
Vector3& Vector3::operator-=(const Vector3& rhs)
{
this->x -= rhs.x;
this->y -= rhs.y;
this->z -= rhs.z;
return *this;
}
Vector3& Vector3::operator*=(const Vector3& rhs)
{
this->x *= rhs.x;
this->y *= rhs.y;
this->z *= rhs.z;
return *this;
}
Vector3& Vector3::operator/=(const Vector3& rhs)
{
this->x /= rhs.x;
this->y /= rhs.y;
this->z /= rhs.z;
return *this;
}
Vector3& Vector3::operator+=(double s)
{
this->x += s;
this->y += s;
this->z += s;
return *this;
}
Vector3& Vector3::operator-=(double s)
{
this->x -= s;
this->y -= s;
this->z -= s;
return *this;
}
Vector3& Vector3::operator*=(double s)
{
this->x *= s;
this->y *= s;
this->z *= s;
return *this;
}
Vector3& Vector3::operator/=(double s)
{
this->x /= s;
this->y /= s;
this->z /= s;
return *this;
}
}
example - main.cpp
#include "aml.h"
int main(int argc, char** argv)
{
aml::Vector3 v1(1.0, 2.0, 3.0);
aml::Vector3 v2(4.0, 5.0, 6.0);
aml::Vector3 v3 = v1 + v2;
aml::Vector3 v4 = v1 * v2;
std::cout << "v1 : " << v1 << std::endl;
std::cout << "v2 : " << v2 << std::endl;
std::cout << "v3 : " << v3 << std::endl;
std::cout << "v4 : " << v4 << std::endl;
}
test - main.cpp
//File is empty
aml_vector3_test.cpp
#include <catch2/catch_all.hpp>
#include "aml.h"
Final Update (Solution)
I solved the problem by reinstalling vcpkg package manager and cmake tool.
Related
I'm trying to create a R package for my own use, that is using Rcpp and whose C++ code include the Levmar library. I'm working on Windows.
The C++ code works fine when I build it using CMake for example and run it with Visual Studio. But when I put this code in my R package and try to build it, I get the following error :
levmar_example_r.o:levmar_example_r.cpp:(.text+0x281): undefined reference to `dlevmar_der'
(dlevmar_der is declared in levmar.h which is included in my R package, see below)
I have already read quite a lot of SO posts on how to build a R package with external libraries like this or this but it didn't help me to solve my problem.
The structure of my package :
bin/
|- levmar.lib
inst/
|- include/
|- levmar.h
man/
R/
src/
|- Makevars
|- Makevars.win
|- levmar_example_r.cpp
|- RcppExports.cpp
src-i386/
DESCRIPTION
NAMESPACE
Content of Makevars/Makevars.win
PKG_LIBS = -L../bin -llevmar
PKG_CPPFLAGS = -I../inst/include
The C++ code (levmar_example_r.cpp)
#include <iostream>
#include <levmar.h>
#include <math.h>
#include <Rcpp.h>
void fun(double *p, double *x, int m, int n, void *data_){
double a = p[0];
double b = p[1];
double *data = (double *) data_;
for(int i = 0; i < n; i++){
x[i] = log(a*data[i]+b);
}
}
void jacFun(double *p, double *jac, int m, int n, void *data_){
double a = p[0];
double b = p[1];
double *data = (double *) data_;
int k, l;
for(l=k=0; l < n; l++){
jac[k++] = data[l]/(a*data[l]+b);
jac[k++] = 1/(a*data[l]+b);
}
}
// [[Rcpp::export]]
void test_levmar(){
int m = 2; // # of parameters
int n = 40; // # of observations
double a = 1.0;
double b = 2.0;
double data[] = {0.119047619047619, 0.238095238095238, 0.357142857142857, 0.476190476190476, 0.595238095238095, 0.714285714285714, 1.07142857142857, 1.42857142857143,
0.119047619047619 ,0.238095238095238, 0.357142857142857, 0.476190476190476, 0.595238095238095, 0.714285714285714 ,1.07142857142857, 1.42857142857143 ,
0.119047619047619, 0.238095238095238, 0.357142857142857, 0.476190476190476, 0.595238095238095, 0.714285714285714, 1.07142857142857, 1.42857142857143,
0.119047619047619, 0.238095238095238, 0.357142857142857, 0.476190476190476 ,0.595238095238095, 0.714285714285714, 1.07142857142857, 1.42857142857143,
0.119047619047619, 0.238095238095238 ,0.357142857142857, 0.476190476190476, 0.595238095238095, 0.714285714285714, 1.07142857142857, 1.42857142857143};
double popti[2];
popti[0] = a; popti[1] = b;
double x[40];
fun(popti, x, m, n, (void *) data);
// algorithm parameters
double opts[LM_OPTS_SZ], info[LM_INFO_SZ];
opts[0]=LM_INIT_MU;
// stopping thresholds for
opts[1]=1E-10; // ||J^T e||_inf
opts[2]=1E-10; // ||Dp||_2
opts[3]=1E-10; // ||e||_2
opts[4]= LM_DIFF_DELTA; // finite difference if used
double p[2];
p[0] = 3.0; p[1] = 1.0;
dlevmar_der(fun,jacFun,p,x,m,n,100,opts,info,NULL,NULL,(void *) data);
std::cout << "Optimum found:" << std::scientific << std::setprecision(8)<< "\t"<< p[0]<< "\t" << p[1]<< std::endl;
}
I have also tried to put all headers of the levmar library in the inst/include folder and all the .c files in a src/levmar folder and consequently remove
PKG_LIBS = -L../bin -llevmar
in Makevars/Makevars.win and add
-I src/levmar
to the PKG_CPPFLAGS but it didn't work out either.
Do you have any idea on what I should do ?
Don't hesitate to ask for precisions if I wasn't clear enough
SODD got the better of me. I have build a very rough package that compiles the levmar code and creates an initial R package from it: https://github.com/rstub/levmaR. Important points:
Source files in sub-directories of src are not automatically compiled. One has to add them somehow, e.g.
CXX_STD = CXX11
PKG_LIBS=-L. -llevmar $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
PKG_CPPFLAGS=-I./levmar/ -DSTRICT_R_HEADERS
all: $(SHLIB)
$(SHLIB): liblevmar.a
LIBOBJS = levmar/lm.o levmar/Axb.o levmar/misc.o levmar/lmlec.o levmar/lmbc.o \
levmar/lmblec.o levmar/lmbleic.o
liblevmar.a: $(LIBOBJS)
$(AR) rcs liblevmar.a $(LIBOBJS)
By default levmar tries to build single- and double-precision functions and tries to use LAPACK. Default builds of R only include double-precision LAPACK and BLAS. I disabled the single precision build.
The levmar library is actually pure C. So my suspicion that your problems where caused by the different C++ ABIs between VC and gcc is probably not correct. Most likely there is some other incompatibility between VC and gcc concerning the layout of static libraries.
Right now the only available function is your test_levmar(). Tested on Linux and Windows (via Appveyor and rhub).
I have a small C++ test project which should result in a .so-library on Windows Subsystem for Linux (WSL, more or less = Ubuntu 14.x). In order to get a PHP extension the current version of the PHP-CPP library is linked to the project. The compiler is g++ 4.8 on Linux and remotely operated from Visual Studio. In the properties I add -fpic for compiling and -lphpcpp to link libphpcpp.so. Using the old version of Visual Studio 2017 (until 02/2018) everything behaved well and the build was fine.
After updating to the current version of Visual Studio 2017 (15.5.6, 02/2018) the build ends in numerous linking errors of the same type: /usr/bin/ld : error : relocation x has invalid symbol index y, where the numbers x and y vary.
I have no idea what happens here.
The small project consists uses the ideas from here:
DLL in Visual Studio
... and ...
PHP-CPP first extension
The linking options recorded in Visual Studio:
-o"C:\Users\Robert\Documents\Lightning Talk\MathFuncs\MathFuncs\bin\x64\Release\MathFuncs.out" "3600000"
-Wl,-z,relro -Wl,--print-map -Wl,-z,noexecstack -Wl,--trace -Wl,
--verbose -Wl,--no-undefined "g++" -l"phpcpp" -Wl,-z,now
The last lines of the ld/g++ error messages:
1>/usr/bin/ld : error : relocation 15 has invalid symbol index 13
1>/usr/bin/ld : error : relocation 16 has invalid symbol index 13
1>/usr/bin/ld : error : relocation 17 has invalid symbol index 13
1>/usr/bin/ld : error : relocation 18 has invalid symbol index 13
1>/usr/bin/ld : error : relocation 19 has invalid symbol index 21
1>/usr/bin/ld : error : relocation 0 has invalid symbol index 2
1>/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o : error :
1>collect2 : error : ld returned 1 exit status
1>Die Erstellung des Projekts "MathFuncs.vcxproj" ist abgeschlossen -- FEHLER.
My code is here:
MathFuncs.h:
#pragma once
#include <stdexcept>
using namespace std;
// This class is exported from the MathFuncsDll.dll
class MathFuncs
{
public:
// Returns a + b
static double Add(double a, double b);
// Returns a - b
static double Subtract(double a, double b);
// Returns a * b
static double Multiply(double a, double b);
// Returns a / b
// Throws const std::invalid_argument& if b is 0
static double Divide(double a, double b);
};
double MathFuncs::Add(double a, double b)
{
return a + b;
}
double MathFuncs::Subtract(double a, double b)
{
return a - b;
}
double MathFuncs::Multiply(double a, double b)
{
return a * b;
}
double MathFuncs::Divide(double a, double b)
{
if (b == 0)
{
throw invalid_argument("b cannot be zero!");
}
return a / b;
}
... and main.cpp:
#include <iostream>
#include <phpcpp.h>
#include "MathFuncs.h"
Php::Value phpAdd(Php::Parameters ¶ms)
{
auto a(0.0);
a = params[0];
auto b(0.0);
b = params[1];
return MathFuncs::Add(a, b);
}
Php::Value phpSubtract(Php::Parameters ¶ms)
{
auto a(0.0);
a = params[0];
auto b(0.0);
b = params[1];
return MathFuncs::Subtract(a, b);
}
Php::Value phpMultiply(Php::Parameters ¶ms)
{
auto a(0.0);
a = params[0];
auto b(0.0);
b = params[1];
return MathFuncs::Multiply(a, b);
}
Php::Value phpDivide(Php::Parameters ¶ms)
{
auto a(0.0);
a = params[0];
auto b(0.0);
b = params[1];
return MathFuncs::Divide(a, b);
}
extern "C" {
/**
* Function that is called by PHP right after the PHP process
* has started, and that returns an address of an internal PHP
* strucure with all the details and features of your extension
*
* #return void* a pointer to an address that is understood by PHP
*/
PHPCPP_EXPORT void *get_module()
{
// static(!) Php::Extension object that should stay in memory
// for the entire duration of the process (that's why it's static)
static Php::Extension extension("phpMathFuncs", "1.0"); // To be humble, we can change the version number to 0.0.1
extension.add<phpAdd>("Add", {
Php::ByVal("a", Php::Type::Float),
Php::ByVal("b", Php::Type::Float)
});
extension.add<phpSubtract>("Subtract", {
Php::ByVal("a", Php::Type::Float),
Php::ByVal("b", Php::Type::Float)
});
extension.add<phpMultiply>("Multiply", {
Php::ByVal("a", Php::Type::Float),
Php::ByVal("b", Php::Type::Float)
});
extension.add<phpDivide>("Divide", {
Php::ByVal("a", Php::Type::Float),
Php::ByVal("b", Php::Type::Float)
});
// return the extension
return extension;
}
}
In the project properties/general the had been "application (.out)". Changing it to "dynamic library (.so)" solved the problem.
I'm trying to create a Qt application and I need a math expression evaluator to evaluate things like this e.g. (4+5)*2-9/3.
I included the .hpp file of this library (http://www.partow.net/programming/exprtk/) to my project in the Qt Creator and tried to launch the following example of code:
#include <cstdio>
#include <string>
#include "exprtk.hpp"
int main()
{
typedef exprtk::expression<double> expression_t;
typedef exprtk::parser<double> parser_t;
std::string expression_string = "3 + sqrt(5) + pow(3,2) + log(5)";
expression_t expression;
parser_t parser;
if (parser.compile(expression_string,expression))
{
double result = expression.value();
printf("Result: %19.15\n",result);
}
else
printf("Error in expression\n.");
return 0;
}
When I try to compile and run it I get the following output:
debug\main.o:-1: error: too many sections (62303)
What could be the problem?
Using just pure Qt you can do something like this:
QString expression_string("3 + Math.sqrt(5) + Math.pow(3,2) + Math.log(5)");
QScriptEngine expression;
double my_val=expression.evaluate(expression_string).toNumber();
you can do much more, see HERE and HERE
Actually, on my machine (Qt 5.5, Ubuntu 16.04 with g++ 5.3), the code above does not work.
Despite the answer is quite old, I put my solution in case someone finds it useful.
QScriptEngine uses the JavaScript syntax. So to make the above code work, I had to change the syntax to:
QString expression_string("3 + Math.sqrt(5) + Math.pow(3,2) + Math.log(5)");
QScriptEngine expression;
double my_val=expression.evaluate(expression_string).toNumber();
Following the request in comments, here is how to implement an arithmetic parser using boost::spirit. First, you need to download the boost tarball, don't try to just clone Spirit alone from GitHub, because it has dependencies from other boost libraries.
Boost is huge, so if you want just a subset enough for a parser, you can extract it using bcp. From boost source directory:
cd tools/build/src/engine
./build.sh
cd ../../../bcp
../build/src/engine/b2
cd ../..
dist/bin/bcp fusion/include hana/functional spirit/home/x3 /some/path
bcp will copy all dependencies. You can leave only /some/path/boost directory, because all libraries we need are header only.
Finally, here is the full code of the parser.
#include <iostream>
#include <numeric>
#include <stdexcept>
#include <string>
#include <vector>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/hana/functional/fix.hpp>
#include <boost/hana/functional/overload.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
using namespace boost::spirit;
namespace hana = boost::hana;
// Define AST. The root is `ast::expr`, which is the first left-hand side
// operand and a list of all operations on the right-hand side. Each operand is
// a recursive `variant` that has `ast::expr` inside.
namespace ast
{
struct nil {};
struct signed_;
struct expr;
struct operand : x3::variant<
nil
, double
, x3::forward_ast<signed_>
, x3::forward_ast<expr>
>
{
using base_type::base_type;
using base_type::operator=;
};
struct signed_
{
char sign;
operand operand_;
};
struct operation
{
char operator_;
operand operand_;
};
struct expr
{
operand first;
std::vector<operation> rest;
};
} // namespace ast
// Give the grammar access to the fields of AST.
BOOST_FUSION_ADAPT_STRUCT(ast::signed_, sign, operand_)
BOOST_FUSION_ADAPT_STRUCT(ast::operation, operator_, operand_)
BOOST_FUSION_ADAPT_STRUCT(ast::expr, first, rest)
// Arithmetic expression grammar definition.
namespace ArithExpr
{
x3::rule<class expression, ast::expr > const expression("expression");
x3::rule<class term, ast::expr > const term("term");
x3::rule<class factor, ast::operand> const factor("factor");
auto const expression_def =
term
>> *(
(x3::char_('+') >> term)
| (x3::char_('-') >> term)
);
auto const term_def =
factor
>> *(
(x3::char_('*') >> factor)
| (x3::char_('/') >> factor)
);
auto const factor_def =
x3::double_
| '(' >> expression >> ')'
| (x3::char_('-') >> factor)
| (x3::char_('+') >> factor);
BOOST_SPIRIT_DEFINE(expression, term, factor);
auto calc = expression;
} // namespace ArithExpr
template <typename Iterator>
double CalcArithExpr(Iterator const &first, Iterator last) {
ast::expr expr;
// Build AST.
if (!x3::phrase_parse(first, last, ArithExpr::calc, x3::ascii::space, expr)) {
throw std::runtime_error("Cannot parse arithmetic expression");
}
// Parse the AST and calculate the result.
// hana::fix allows recursive lambda call
auto astEval = hana::fix([](auto self, auto expr) -> double {
// hana::overload calls a lambda corresponding to the type in the variant
return hana::overload(
[](ast::nil) -> double {
BOOST_ASSERT(0);
return 0;
},
[](double x) -> double { return x; },
[&](ast::signed_ const &x) -> double {
double rhs = boost::apply_visitor(self, x.operand_);
switch (x.sign) {
case '-': return -rhs;
case '+': return +rhs;
}
BOOST_ASSERT(0);
return 0;
},
[&](ast::expr const &x) -> double {
return std::accumulate(
x.rest.begin(), x.rest.end(),
// evaluate recursively left-hand side
boost::apply_visitor(self, x.first),
[&](double lhs, const ast::operation &op) -> double {
// evaluate recursively right-hand side
double rhs = boost::apply_visitor(self, op.operand_);
switch (op.operator_) {
case '+': return lhs + rhs;
case '-': return lhs - rhs;
case '*': return lhs * rhs;
case '/': return lhs / rhs;
}
BOOST_ASSERT(0);
return 0;
}
);
}
)(expr);
});
return astEval(expr);
}
int main(int argc, char *argv[]) {
auto expr = std::string{"-(4.5 + 5e-1) * 2.22 - 9.1 / 3.45"};
std::cout << CalcArithExpr(expr.begin(), expr.end()) << std::endl;
}
It calculates -(4.5 + 5e-1) * 2.22 - 9.1 / 3.45 and outputs -13.7377.
Update
Here are instructions how to build bcp and copy selected headers on Windows. Though, without any guarantee. In Linux everything just works, on Windows it is always jumps over some hoops, and the direction of jumps are always unpredictable.
This being said, open PowerShell command line. There
Import-Module 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\Tools\Microsoft.VisualStudio.DevShell.dll'
Install-Module VSSetup -Scope CurrentUser
Get-VSSetupInstance
Substitute 2019 above with your version of VS. You have to do it only once for your PowerShell. The rest is every time you need to build bcp. Get-VSSetupInstance above will print information about the instances of Visual Studio you have on your machine. Write down InstanceId that you would like to use. Now change to the boost directory in the PowerShell, and:
Enter-VsDevShell InstanceId -DevCmdArguments '-arch=x64' -SkipAutomaticLocation
Where InstanceId is the ID you got from Get-VSSetupInstance. Then from the same command prompt
cd tools\build\src\engine
& .\build.bat
cd ..\..\..\bcp
..\build\src\engine\b2 address-model=64
cd ..\..
dist\bin\bcp fusion\include hana\functional spirit\home\x3 X:\some\path\boost
In this qmake code:
MY_COMPILER = mingw
warning($$MY_COMPILER)
contains(MY_COMPILER, mingw)
{
INCLUDEPATH += ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/src
DEPENDPATH += ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/src
QMAKE_RPATHDIR *= ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/lib
contains(QWT_CONFIG, QwtFramework) {
LIBS += -F../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/lib
}
else {
LIBS += -L../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/lib
}
IPATH = ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0/src
warning(Using MinGW compiler)
}
else {
INCLUDEPATH += ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/src
DEPENDPATH += ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/src
QMAKE_RPATHDIR *= ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/lib
contains(QWT_CONFIG, QwtFramework) {
LIBS += -F../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/lib
}
else {
LIBS += -L../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/lib
}
IPATH = ../../libsrc/Qwt/qwt-6.0.1-win-Qt-4.8.0-intel-shared/src
warning(Using Intel compiler)
}
Whatever I define for the variable MY_COMPILER, it keeps taking the first condition, whilst it posts through the warning at line 3 the correct variable I entered.
How can I post a variable and then check whether it's defined?
Any efforts are highly appreciated.
Thanks.
I don't see anything wrong with your code, but you could try it this way instead:
CONFIG += mingw
mingw {
//...
} else {
//...
}
EDIT:
Another thing you could try is have the condition and opening curly bracket in the same line,
if I remember right, that caused some problems in the past.
Then the statement would look like this:
contains(MY_COMPILER, mingw) {
//...
} else {
//...
}
I can not seem to be able to read from config file multitoken options like I can from command line. What is the syntax for the config file?
This is how the option description is added:
//parser.cpp
- - -
po::options_description* generic;
generic=new po::options_description("Generic options");
generic->add_options()
("coordinate",po::value<std::vector<double> >()->multitoken(),"Coordinates (x,y)");
After which I parse command and config-files.
On command line '--coordinate 1 2' works. However, when I try in config file:
coordinate = 1,2
or
coordinate= 1 2
It fails giving a invalid_option_value exception. So what exactly is the syntax for config files in case of multitoken options?
In your configuration file, put each element of your vector on a different line.
coordinate=1
coordinate=2
You can achieve the behavior you seek by writing a custom validator. This custom validator accepts :
./progname --coordinate 1 2
./progname --coordinate "1 2"
#In config file:
coordinate= 1 2
Here is the code:
struct coordinate {
double x,y;
};
void validate(boost::any& v,
const vector<string>& values,
coordinate*, int) {
coordinate c;
vector<double> dvalues;
for(vector<string>::const_iterator it = values.begin();
it != values.end();
++it) {
stringstream ss(*it);
copy(istream_iterator<double>(ss), istream_iterator<double>(),
back_inserter(dvalues));
if(!ss.eof()) {
throw po::validation_error("Invalid coordinate specification");
}
}
if(dvalues.size() != 2) {
throw po::validation_error("Invalid coordinate specification");
}
c.x = dvalues[0];
c.y = dvalues[1];
v = c;
}
...
po::options_description config("Configuration");
config.add_options()
("coordinate",po::value<coordinate>()->multitoken(),"Coordinates (x,y)")
;
References:
http://www.boost.org/doc/libs/1_46_1/doc/html/program_options/howto.html#id2219998
https://stackoverflow.com/tags/boost-program-options/hot
Handle complex options with Boost's program_options
During finding myself confronted with a similar problem, I took the code above from Rob's answer (from May 4th, 2011), but had to change a few things due to changes in the boost architecture and C++11. I only cite the parts that I changed (or would have changed). The rest that is not within the validate function stays the same. For conformity reasons, I added the necessary std:: prefixes.
namespace po = boost::program_options;
void validate(boost::any& v,
const std::vector<std::string>& values,
coordinate*, int) {
coordinate c;
std::vector<double> dvalues;
for(const auto& val : values) {
std::stringstream ss(val);
std::copy(std::istream_iterator<double>(ss), std::istream_iterator<double>(),
std::back_inserter(dvalues));
if(!ss.eof()) {
throw po::invalid_option_value("Invalid coordinate specification");
}
}
if(dvalues.size() != 2) {
throw po::invalid_option_value("Invalid coordinate specification");
}
c.x = dvalues[0];
c.y = dvalues[1];
v = c;
}
The shift from po::validation_error to po::invalid_option_value was hinted in https://stackoverflow.com/a/12186109/4579106