SCons: How to make a library pick up CPPPATH options - c++

I have boost installed under /home/username/local/include. I want to compile a library with this set under CPPPATH.
SConstruct:
env = Environment(CPPPATH = '/home/username/local/include')
env.Library('MyLib', 'library.cpp')
library.cpp:
#include <boost/shared_ptr.hpp> // library.cpp:1:32: error: boost/shared_ptr.hpp: No such file or directory
void foo() { }
However, when I run scons, it gives the error error: boost/shared_ptr.hpp: No such file or directory.
Doing the same thing for a program works just fine.
SConstruct:
env = Environment(CPPPATH = '/home/username/local/include')
env.Program('program.cpp')
program.cpp:
#include <boost/shared_ptr.hpp> // works
int main() { return 0; }
What am I missing here?
EDIT
Here is the output:
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o library.o -c -I/home/m/local/include library.cpp
library.cpp:1:32: error: boost/shared_ptr.hpp: No such file or directory
scons: *** [library.o] Error 1
scons: building terminated because of errors.

I can't reproduce your error on my system. Everything you have there looks right to me.
I created a faked out boost include setup, and used a different filename so it wouldn't accidentally reach into my real boost includes in /usr. I'm using SCons 2.0.1.
$ find /home/acm/local/include -type f
/home/acm/local/include/boost/not_a_boost_header.hpp
library.cpp:
#include <boost/not_a_boost_header.hpp>
void foo() { }
program.cpp:
#include <boost/not_a_boost_header.hpp>
int main() { return 0; }
SConstruct:
env1 = Environment(CPPPATH = '/home/acm/local/include')
env1.Library('MyLib', 'library.cpp')
env2 = Environment(CPPPATH = '/home/acm/local/include')
env2.Program('program.cpp')
Build results:
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o library.o -c -I/home/acm/local/include library.cpp
ar rc libMyLib.a library.o
ranlib libMyLib.a
g++ -o program.o -c -I/home/acm/local/include program.cpp
g++ -o program program.o
scons: done building targets.
Can you post the complete SCons output?

Related

clang++ always generates empty profraw coverage reports

I'm trying to integrate coverage in C++ with clang 6 for the first time and have been following this guide.
I successfully compiled the binary, generated a .profraw file and generated a .profdata file as described in steps 1, 2 and 3a. But when I try to create a line-oriented coverage report as described in 3b, I receive the following message:
error: build/debug/dane: Failed to load coverage: No coverage data found
Upon checking the .profraw file, I found it was empty. I tried changing my code a bit and running again but the generated .profraw was always empty.
My main.cpp file:
#include <iostream>
int main(int argc, char **argv) {
std::cout << "Hello, World!" << std::endl;
return 0;
}
My SConstruct file:
env = Environment(CXX='clang++', CXXFLAGS=['-Wall', '-g', '-O0'], LINKFLAGS=['-fprofile-instr-generate', '-fcoverage-mapping'])
env.Program(target='build/debug/dane', source=['src/main.cpp'])
Command line output:
➤ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
clang++ -o src/main.o -c -Wall -g -O0 src/main.cpp
clang++ -o build/debug/dane -fprofile-instr-generate -fcoverage-mapping src/main.o
scons: done building targets.
➤ build/debug/dane
Hello, World!
➤ llvm-profdata merge -sparse default.profraw -o default.profdata
➤ llvm-cov show build/debug/dane -instr-profile=default.profdata
error: build/debug/dane: Failed to load coverage: No coverage data found
I expected the default.profraw file to hold meaningful coverage results, and have no clue why it's empty.
Finally solved it.
At first I gave the -fprofile-instr-generate -fcoverage-mapping flags as CXXFLAGS, but it didn't work, and so I understood that these were linker flags and moved them to the LINKFLAGS (which resulted in this frustrated post).
Apparently, these flags need to appear both as compilation and linker flags in order for the whole thing to work.
I also tried checking if you can distribute the flags between the compiler and the linker but that didn't succeed.

scons env.InstallAs() doesn't seem to copy any file?

For example, I've a .c file as below:
$cat hello.c
int main(){
return 0;
}
Then I use scons to build and copy it to some place:
$cat SConstruct
import os,sys
env = Environment()
hello = env.Program('hello.c')
env.InstallAs('/home/admin/hello-new', hello)
run scons under user named 'admin' it prints:
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o hello.o -c hello.c
gcc -o hello hello.o
scons: done building targets.
Then I tried to "ls /home/admin" there's no such a thing like "hello-new". So I wonder why my "env.InstallAs()" worked at all? How to trouble-shoot and fix it?
Thanks.
Please read the FAQ, this is a common misunderstanding about SCons and thus in the FAQ:
https://scons.org/faq.html#How_do_I_install_files.3F_The_Install.28.29_method_doesn.27t_do_anything._In_general.2C_how_do_I_build_anything_outside_my_current_directory.3F
With your example changing to this should cause it to always build the target in question:
import os,sys
env = Environment()
hello = env.Program('hello.c')
install_target = env.InstallAs('/home/admin/hello-new', hello)
# Always build the install target by default
Default(install_target)

Scons: how to check file before compilation with commands which doesn't product any output file?

I work with project in which every object files is being built 3 times:
With newest g++ with lots of flags in order to find every possible errors and warnings
With clang in order to do as above and check style.
With g++ compatible with 3rdpart libraries (no newer version, but entire product is based of the libraries)
It works that way: if any object file should be recompiled: the steps 1, if success then 2, if success then 3 is being done. It is done with makefile, but I'm planning to use scons to do its. The problem is that in current solution object file from 1 and 2 is being saved into /dev/null.
I've tried something line this:
3 files in the same directory: hello.cc, Sconstruct, Sconscript
SConstruct
#!python
warningFlags = ' -Wall -Wextra -Werror' # and many more
env = Environment(CXX = 'g++-4.8', parse_flags = warningFlags, CPPPATH = '.')
builtObjects = env.SConscript('SConscript', variant_dir='built', duplicate=0, exports='env')
env.Program(target = 'hello', source = builtObjects)
SConscript
#!python
Import('env')
builtObjects = env.Object(source = 'hello.cc')
checkWithClang = env.Command('/dev/null', builtObjects, 'clang -o $TARGET -Wall -Werror')
env.Depends(checkWithClang, builtObjects)
Return('builtObjects')
The output from scons is:
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: building associated VariantDir targets: built
g++-4.8 -o built/hello.o -c -Wall -Wextra -Werror -Ibuilt -I. hello.cc
g++-4.8 -o hello built/hello.o
scons: done building targets.
EDIT:
Is it possible to somehow check in scons:
if object file should be rebuilt?
Pseudo code:
src = 'hello.cc'
if shouldObjectFileBeRebuilt(src):
checkWithClang = env.Command('/dev/null', builtObjects, 'clang -o $TARGET -Wall -Werror')
builtObjects = env.Object(source = src)
env.Depends(checkWithClang, builtObjects)
try
src = "hello.cc"
builtObjects = env.Object(source = src)
checkWithClang = env.Command('/dev/null', src, 'clang -o $TARGET -Wall -Werror')
env.Depends(builtObjects, checkWithClang)
buildobjects represent '.o' files, so you should put '.c' files to clang
you want buildObjects to be built after clang objects - change the order
Still - building into /dev/null will probably break dependency tree, you might consider something like:
checkWithClang = env.Object(source = src, CC="clang", OBJPREFIX="clang-")
this will build all .c files with clang and store extra .o files, allowing scons to rebuild only what is necessarry

Defining C++ Preprocessor macros with SCons

I'm trying to define a preprocessor macro within Scons for building a larger C/C++ project.
One of the libraries I'm using needs ALIGN defined. To be more specific, if I add
#define ALIGN(x) __attribute((aligned(x)))
to the header file of said library, it compiles fine. However, I should be able to specify this at build time, as this is how the library intends on being used. I know in CMake, I would be able to define the macro using something like
SET(ALIGN_DECL "__attribute__((aligned(x)))")
Defining constants in Scons like this
myEnv.Append(CPPDEFINES = ['IAMADEFINEDCONSTANT'])
works fine, but definine a macro in this way doesn't work.
What gives?
Edit: fixed typo
I was able to do it on Linux with g++ as follows:
SConscript
env = Environment()
env.Append(CPPDEFINES=['MAX(x,y)=(x>y ? x:y)'])
env.Program(target = 'main', source = 'main.cc')
main.cc
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
int a = 3;
int b = 5;
// MAX() will be defined at compile time
cout << "Max is " << MAX(a, b) << endl;
}
Compilation
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o main.o -c "-DMAX(x,y)=(x>y ? x:y)" main.cc
g++ -o main main.o
scons: done building targets.
Execution
./main
Max is 5

Error: undefined reference to `sqlite3_open'

I'm trying to get started with the C++ API for SQLite.
#include <iostream>
#include <sqlite3.h>
using namespace std;
int main()
{
sqlite3 *db;
if (sqlite3_open("ex1.db", &db) == SQLITE_OK)
cout << "Opened db successfully\n";
else
cout << "Failed to open db\n";
return 0;
}
Compiling this using the command "g++ main.cpp" gives the following error:
/tmp/ccu8sv4b.o: In function `main':
main.cpp:(.text+0x64): undefined reference to `sqlite3_open'
collect2: ld returned 1 exit status
What could have gone wrong? Hasn't sqlite3 properly installed in the server I'm compiling this in?
You need to link the sqlite3 library along with your program:
g++ main.cpp -lsqlite3
You need to adjust your linker flags to link in the sqlite3 library. Libraries are usually installed in /usr/lib or /usr/lib64
Alternatively, you can copy the sqlite3.c file to your project directory and compile it as part of the g++ command:
g++ main.cpp sqlite3.c
as per: http://sqlite.org/cvstrac/wiki?p=HowToCompile
First step: Install all library sqlite3 with the command:
sudo apt-get install libsqlite3-dev
With that you can use #include <sqlite3.h> in a programm of C or C++.
Second step: To compile the program by console:
C++:
g++ program.cpp -o executable -lsqlite3
./executable
C:
gcc program.c -o executable -lsqlite3
./executable
Either link your program to lib g++ yourProgram.c -lsqlite3 in command line or in Open IDE -> project -> properties -> locate lib file for sqlite3 .
Compile using Devcpp
1. add sqlite3.dll file in the project folder.
2. go to Compiler option in Tools >>
3. write sqlite3.dll next to >> Add the following commands when calling compiler
Compile using command line
NOTE : install MinGW (compiler)
g++ file.cpp -o output.exe sqlite3.dll
Compile using VS
define sqlite3.dll in linker in project properties