Boost Test and QtTest memory access violation with Botan - boost-test

I've been struggling with this and so far couldn't make it work. A simple main using botan works fine, but when i put the same code in a unittest it fails.
// keygeneration_test.cpp
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp> // shuold use this one if using dynamic linking
#include <botan\botan.h>
#include <botan\rsa.h>
BOOST_AUTO_TEST_SUITE(keygeneration_suite)
BOOST_AUTO_TEST_CASE(rsa_key_generation)
{
BOOST_TEST_MESSAGE("generating key");
try
{
Botan::LibraryInitializer init;
Botan::AutoSeeded_RNG rng;
rng.reseed(10096);
Botan::RSA_PrivateKey rsaPrivate(rng, 1024);
}
catch (std::exception& e)
{
BOOST_TEST_MESSAGE(e.what());
}
}
BOOST_AUTO_TEST_SUITE_END()
--
// main.cpp
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE cryptography test //module define should be only here, it takes care of creating entry point
#include <boost/test/unit_test.hpp> // should use this one if using dynamic linking
I then tried putting the init in the main entry point like this:
//main.cpp
#define BOOST_TEST_DYN_LINK // Make the exe link dynamically
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp> // should use this one if using dynamic linking
#include <botan\botan.h>
bool init_function()
{
return true;
}
int main(int argc, char* argv[])
{
Botan::LibraryInitializer init;
return boost::unit_test::unit_test_main(&init_function, argc, argv);
}
They both show the same error:
Running 1 test case... unknown location(0): fatal error in
"rsa_key_generation": memory access violation occurred at address
0x00141000, while attempting to read inaccessible data
*** 1 failure detected in test suite "cryptography test" Detected memory leaks! Dumping objects -> {670} normal block at
0x0000000000221380, 16 bytes long. Data: 78 EA 13
00 00 00 00 00 00 00 00 00 00 00 00 00 Object dump complete.
Just for the record, a simple test for compression that i tried or whatever i did works fine, but when i try to create a test with botan initialization it fails no matter what i try.
Edit: I've tried with Qt Test and the same happens. Its is really weird. Has anyone experienced something like this? Could anyone reproduce this?

Found the annoying problem. Code Generation was set to Multi-threaded DEBUG DLL. For some reason changing to Multi-threaded DLL makes it work. I guess maybe because botan was compiled for release. (it would be nice to have a hint or suggestion from the compiler...)

Related

Can I inline a function which uses a static variable?

I have this code:
// my.h
#ifndef MY_HEADER
#define MY_HEADER
int create_uid();
#endif
// my.cpp
#include "my.h"
static int _next_uid = 0;
int create_uid()
{
return _next_uid++;
}
I want to inline create_uid(), while keeping the _next_uid variable global to the program so the variable is unique.
My questions are:
Can I do this?
Is the inline statement require _next_uid to be visible outside the compilation unit?
Note: This doesn't seems to answer those questions clearly.
Edited after clarifiation of the question.
If you want only a single _next_uid, then simply put the following into your header file:
inline int create_uid()
{
static int _next_uid = 0;
return _next_uid++;
}
Short answer. No. The following code
// my.h
static int _next_uid = 0;
inline int create_uid() {
return _next_uid++;
}
will probably compile, but will result in undefined behaviour if used in more than one translation units. This is because the _next_uid variables are different entities in different translation units. Thus the definitions of create_uid() are also different. However:
If an inline function [...] with external linkage is defined differently in different translation units, the behavior is undefined. [1]
What you can do instead is either use a local scope static variable in the function, like #DanielLangr showed in one of the other answers [1]. This has the disadvantage, that that variable cannot be accessed outside of the function. Alternatively as #wohlstad mentioned in one of the comments, you can use a C++17 inline variable:
// my.h
inline int _next_uid = 0;
inline int create_uid() {
return _next_uid++;
}
Note that this does not define a static variable. Using static and inline will have the same effect as just using static [3], which results in the undefined behaviour I mentioned above.
Inlining a function means per definition, that all the variables it uses must be reachable from the translation unit where it is inlined. This cannot work with a unique static (thus not visible to other TUs) variable.
[1]: https://en.cppreference.com/w/cpp/language/inline
[2]: https://stackoverflow.com/a/72124623/17862371
[3]: https://stackoverflow.com/a/58101307/17862371
Summary:
It doesn't work if you put implementation of inline next_id() to a single c file, which means the function is in a single compile unit. So main cannot find inline next_id(), you'll get the error undefined reference.
It can be compiled if you declare inline next_id() in a shared header file, in which case each compile unit will properly find inline next_id().
In my case, only one instance of this global variable will appear in virtual address space .DATA segment of the process. The output number is continuous.
Example:
Makefile 8:
all:
c++ -c main.cpp
c++ -c second.cpp
c++ -c share.cpp
c++ main.o second.o share.o -o main
clean:
rm -f main.o second.o share.o main
main.cpp 12:
#include <cstdio>
#include "share.hpp"
#include "second.hpp"
int main(){
printf("[main] %d\n", next_id());
consume_id();
printf("[main] %d\n", next_id());
consume_id();
printf("[main] %d\n", next_id());
return 0;
}
second.hpp 1:
void consume_id();
second.cpp 7:
#include <cstdio>
#include "share.hpp"
void consume_id(){
printf("[scnd] %d\n", next_id());
}
share.hpp 4:
#pragma once
int next_id();
share.cpp 7:
static int _next_id = 0;
int next_id()
{
return _next_id++;
}
Result output:
[main] 0
[scnd] 1
[main] 2
[scnd] 3
[main] 4
But if it is changed to:
share.cpp 4:
inline int next_id()
{
return _next_id++;
}
undefined reference to `next_id()'
If changed to
share.hpp 7:
#pragma once
static int _next_id = 0;
inline int next_id()
{
return _next_id++;
}
Works
EDIT:
It seems to be an undefined behavior
I'm using `gcc version 11.2.0 (Ubuntu 11.2.0-19ubuntu1)
IN MY CASE
You will have copies of static int _next_id but only in the object file. In memory there is only one.
objdump -d main > main.s
main.s 143:
00000000000011b3 <_Z7next_idv>:
11b3: f3 0f 1e fa endbr64
11b7: 55 push %rbp
11b8: 48 89 e5 mov %rsp,%rbp
11bb: 8b 05 53 2e 00 00 mov 0x2e53(%rip),%eax # 4014 <_ZL8_next_id>
11c1: 8d 50 01 lea 0x1(%rax),%edx
11c4: 89 15 4a 2e 00 00 mov %edx,0x2e4a(%rip) # 4014 <_ZL8_next_id>
11ca: 5d pop %rbp
11cb: c3 ret
Here function _Z7next_idv only appears in memory for 1 time.
main.s 147:
11bb: 8b 05 53 2e 00 00 mov 0x2e53(%rip),%eax # 4014 <_ZL8_next_id>
The label of _next_id is _ZL8_next_id, only appears in memory for 1 time as well.

How to interpret or narrow down the cause of a memory leak in this visual leak detector output?

How do I narrow down the cause to find the reason for the memory leak reported in this Visual Leak Detector output?
The question is not to debug this particular code for me, but how to approach problems like this in general. Visual Leak Detector reports many leaks and questions like this are quite frequent here on SO therefore I hope for an answer which is less specific but more general such that it is not only help in this particular case but more for others as well.
---------- Block 305 at 0x00000000FCBFBBB0: 64 bytes ----------
Leak Hash: 0x7DAD966C, Count: 1, Total 64 bytes
Call Stack (TID 11728):
ucrtbased.dll!malloc()
e:\programme (x86)\microsoft visual studio 14.0\vc\include\xmemory0 (901): Shady.exe!std::_Wrap_alloc<std::allocator<std::_List_node<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::unique_ptr<Texture,std::default_delete<Texture> > >,void * __ptr64> > >::allocate()
e:\programme (x86)\microsoft visual studio 14.0\vc\include\list (730): Shady.exe!std::_List_alloc<std::_List_base_types<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::unique_ptr<Texture,std::default_delete<Texture> > >,std::allocator<std::pair<std::basic_string<char,std::char_traits<char>,st() + 0x19 bytes
e:\programme (x86)\microsoft visual studio 14.0\vc\include\list (716): Shady.exe!std::_List_alloc<std::_List_base_types<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::unique_ptr<Texture,std::default_delete<Texture> > >,std::allocator<std::pair<std::basic_string<char,std::char_traits<char>,st()
e:\programme (x86)\microsoft visual studio 14.0\vc\include\list (631): Shady.exe!std::_List_alloc<std::_List_base_types<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::unique_ptr<Texture,std::default_delete<Texture> > >,std::allocator<std::pair<std::basic_string<char,std::char_traits<char>,st() + 0xC bytes
e:\programme (x86)\microsoft visual studio 14.0\vc\include\list (818): Shady.exe!std::_List_buy<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::unique_ptr<Texture,std::default_delete<Texture> > >,std::allocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > con()
e:\programme (x86)\microsoft visual studio 14.0\vc\include\list (896): Shady.exe!std::list<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,std::unique_ptr<Texture,std::default_delete<Texture> > >,std::allocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,s()
e:\programme (x86)\microsoft visual studio 14.0\vc\include\xhash (197): Shady.exe!std::_Hash<std::_Umap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::unique_ptr<Texture,std::default_delete<Texture> >,std::_Uhash_compare<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::hash<std() + 0x1A bytes
e:\programme (x86)\microsoft visual studio 14.0\vc\include\unordered_map (119): Shady.exe!std::unordered_map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::unique_ptr<Texture,std::default_delete<Texture> >,std::hash<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::equal_to<std::basic_string()
e:\repositories\shady\src\texture\texturemanager.h (39): Shady.exe!TextureManager::TextureManager() + 0x44 bytes
e:\repositories\shady\src\engine.h (53): Shady.exe!Engine::Engine() + 0x65 bytes
e:\repositories\shady\src\engine.cpp (97): Shady.exe!main() + 0x1D bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (75): Shady.exe!invoke_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (264): Shady.exe!__scrt_common_main_seh() + 0x5 bytes
f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl (309): Shady.exe!__scrt_common_main()
f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp (17): Shady.exe!mainCRTStartup()
KERNEL32.DLL!BaseThreadInitThunk() + 0x22 bytes
ntdll.dll!RtlUserThreadStart() + 0x34 bytes
Data:
B0 BB BF FC B4 01 00 00 B0 BB BF FC B4 01 00 00 ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
engine.cpp 97 is Engine engine = Engine(); which constructs an object of this class
class Engine{
Engine() : _logger("Engine"){}
TextureManager _textureManager;
Logger mutable _logger;
};
while texturemanager.h 39 is TextureManager() :_logger("TextureManager"){}; of this class:
class TextureManager{
TextureManager() :_logger("TextureManager"){};
~TextureManager() {
for (const auto& kv : _textures) {
GLuint h = kv.second->getTextureHandle();
glDeleteTextures(1, &h);
}
}
std::unordered_map<std::string, std::unique_ptr<Texture>> _textures;
Logger mutable _logger;
};
Did I understand the output correctly that the unordered_map causes the leak? There is no direct allocation with new or malloc involved in this code as I try to completly move to shared and unique pointers. Could the string passed to the constructors and reused and stored in the classes the problem? From what I read std::string does manage its memory itself.
How do I narrow down the cause to find the reason for the memory leak
It's possible that you've stumbled on a memory leak in the STL implementation used by your compiler. The best way to narrow this down is to eliminate as many culprits as possible and build an SSCCE or MVCE that does nothing but use the guilty-seeming unordered_map.
#include <memory>
#include <string>
#include <unordered_map>
int main()
{
std::unordered_map<std::string, std::unique_ptr<std::string>> uomap; //1
uomap["hello"] = std::make_unique<std::string>("world"); //2
return uomap.size() - 1;
}
http://ideone.com/a3hIaj
Start the program with your leak detector and determine whether you still see the leak or not. If you do, congratulations on your bug find, you'll want to report the bug to your STL vendor.
Incidentally, if you are using Microsoft's implementation, you may find it interesting to note that the construction of an unordered_map involves a number of mallocs. You can verify this by setting breakpoints on the lines marked //1 and //2 and starting the program.
When breakpoint #1 hits, select Debug -> New Breakpoint -> Function Breakpoint and set a breakpoint on 'malloc'. Now press F5 - if you want to see the stack traces inside the STL/CRT check the "Microsoft Symbol Servers" box and click OK.
You'll find that there are 3-4 calls to malloc just in the construction of the unordered_map.
One common problem with memory leak detection is that a memory leak is essentially nothing else than not freed memory at the time the detector analyzes the snapshot.
It looks like the most common false-positive memory leak warnings are static or global variables which are not freed at the time the memory leak dump is created, but will be freed at a later moment.
This makes finding actual leaks more tedious and difficult if you aren't very profound with why some code leaks in the first place. The tool of choice might report a leak where there is none, but you might not understand why.
The first things to check for any reported memory leaks are
Is a static/global variables involved?
Is it necessary to handle them at all or will they be cleaned up properly when the context is released?
Are containers properly cleaned up?
Is inheritance involved?
If instances of sub classes are stored in pointers of a any base class, do all base classes contain proper virtual destructors?
Is memory allocated with new, mallocor similar?
Is this memory cleaned up with delete, delete[] or free or similar?
Similar to the Comment Out Debugging-technique it is possible to use memory snapshots to narrow down where memory is leaked. The following example is for Visual Studio but the very same idea can be used with any functionality which allows for memory snapshotting.
//Create 3 Memory states, where s3 is the difference
_CrtMemState s1, s2, s3;
//Snapshot the first time
_CrtMemCheckpoint(&s1);
//your questionable code
//Snapshot the second time
_CrtMemCheckpoint(&s2);
//If there is a difference between both states, there is a memory leak
if _CrtMemDifference(&s3, &s1, &s2)
_CrtMemDumpStatistics(&s3);
This idea can be wrapped into a combination of macros and a class to allow for proper context utilization. Combined with the #ifdef _DEBUG method to only include the code for a DEBUG build you can leave your memory leak detection in your code without performance loss as those macros will be replaced with no-op for a non-DEBUG build and those should be optimized out by any modern compiler.
Wrapped in macros and a class along with a stack this can be used as follows:
#include <MemoryLeakDetector.h>
void foo() {
BEGINMEMORYLEAKCHECK();
int * j = new int;
ENDMEMORYLEAKCHECK();/*Leak 2 of 4 bytes detected.*/
}
int main(void) {
/*Because we use a global stack we can nest our macro use!*/
BEGINMEMORYLEAKCHECK();
BEGINMEMORYLEAKCHECK();
int * i = new int;
ENDMEMORYLEAKCHECK();/*Leak 1 of 4 bytes detected.*/
delete i;/*Leak 1 is closed.*/
foo();/*but we generate a leak 2 of 4 bytes inside of foo*/
ENDMEMORYLEAKCHECK();/*Leak 2 of 4 bytes is detected here as well*/
}
With the following MemoryLeakDetector.h which uses a std::stack of std::unique_ptr<MemoryLeakDetector> to properly handle the different stack contexts. This allows for nested use of our macros. We use std::unique_ptr to not only avoid leaks in our MemoryLeakDetector code but also to allow us to utilize std::move instead of copying the objects.
MemoryLeakDetector.h:
#pragma once
#ifdef _DEBUG
//#include <vld.h> /* Visual Leak Detector Memory Leak Detection*/
#include <crtdbg.h> /*VS Memory Leak Detection*/
#include <stack>
#include <memory>
#include <sstream>
#include "Windows.h"
class MemoryLeakDetector {
public:
MemoryLeakDetector() {};
_CrtMemState MEMORYLEAKSTATISTICS1;
_CrtMemState MEMORYLEAKSTATISTICS2;
_CrtMemState MEMORYLEAKSTATISTICS3;
static std::stack<std::unique_ptr<MemoryLeakDetector>>& stack() {
static std::stack<std::unique_ptr<MemoryLeakDetector>> s;
return s;
}
};
#define DBOUT( s ) \
do{ \
std::ostringstream os; \
os << s; \
OutputDebugString(os.str().c_str() ); \
}while(0)
#define BEGINMEMORYLEAKCHECK() do{std::unique_ptr<MemoryLeakDetector> ___memoryleakdetector___ = std::make_unique<MemoryLeakDetector>();\
MemoryLeakDetector::stack().push(std::move(___memoryleakdetector___));\
_CrtMemCheckpoint(&MemoryLeakDetector::stack().top().get()->MEMORYLEAKSTATISTICS1);\
}while(0)
#define ENDMEMORYLEAKCHECK() do{if(MemoryLeakDetector::stack().size()==0){DBOUT("\n"<<__FILE__<<"("<<__LINE__<<"):"<<"<"<<__FUNCTION__<<" ENDMEMORYLEAKCHECK without BEGINMEMORYLEAKCHECK detected\n");\
break;}\
std::unique_ptr<MemoryLeakDetector> ___memoryleakdetector___ = std::move(MemoryLeakDetector::stack().top());MemoryLeakDetector::stack().pop();\
_CrtMemCheckpoint(&___memoryleakdetector___->MEMORYLEAKSTATISTICS2);\
if (_CrtMemDifference(&___memoryleakdetector___->MEMORYLEAKSTATISTICS3, &___memoryleakdetector___->MEMORYLEAKSTATISTICS1, &___memoryleakdetector___->MEMORYLEAKSTATISTICS2)){\
DBOUT("\n"<<__FILE__<<"("<<__LINE__<<"):"<<"<"<<__FUNCTION__<<"> MLD detected a leak\n");\
_CrtMemDumpStatistics(&___memoryleakdetector___->MEMORYLEAKSTATISTICS3);\
DBOUT("\n\n");\
std::cerr << "MLD Leak detected "<<__FILE__<<"("<<__LINE__<<")"<< std::endl;\
}}while(0)
#else
#define BEGINMEMORYLEAKCHECK() do{}while(0)
#define ENDMEMORYLEAKCHECK() do{}while(0)
#define DBOUT( s ) do{}while(0)
#endif

Error while running boost test project: testcaseName: No such file or directory

I'm trying to make use of boost unit test suite.
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE main_test_module
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>
.... // introducing some functions and variables here
BOOST_AUTO_TEST_CASE(fileComparatorTestCase)
{
Logger() << "Testing file comparator";
bool res;
res = compare(file1Path, file1Path);
BOOST_REQUIRE_EQUAL(res, true);
res = compare(file2Path, file2Path);
BOOST_REQUIRE_EQUAL(res, true);
res = compare(file1Path, file3Path);
BOOST_REQUIRE_EQUAL(res, false);
res = compare(file1Path, file2Path);
BOOST_REQUIRE_EQUAL(res, false);
Logger() << "Ended testing file comparator";
}
I'm also linking boost_unit_test_framework library. This code compiles fine, but when I'm trying to run the testrunner, it fails with following error:
Running 1 test case...
unknown location(0): fatal error in "fileComparatorTestCase": std::exception: No such file or directory
any ideas on how to fix it?
Apparently, either
Logger() can't open the output location for writing; or
the compare function you're testing, checks for the existence of the files/paths you pass.
Try commenting stuff until you find the culprit. If the exception arises from Boost, usually more extensive exception information is available. Otherwise, the source code, or perhaps tricks such as strace can tell you what's happening.

What are the other defines relating to #define KB_UP 72 for c++? What are all of them?

So I'm working to learn about how to get DIRECT keyboard input with c++. Right now i know how to use the getch() function and functions of that nature but I don't know how to define all the different keyboard inputs. These are the kind of ones I'm looking for.
#define KB_UP 72
#define KB_DOWN 80
#define KB_LEFT 75
#define KB_RIGHT 77
#define KB_ESCAPE 27
#define KB_ENTER 28
So ultimately what are the others, are there others? I'm working with c++ on code::blocks on windows.
Thanks in advance :)
Look at the windows API doc for the winapi function GetAsyncKeyState() which has a link to a page listing the virtual key codes returned by this function. The list includes the codes you mention in your q, but they are prefixed with VK_ rather than KB_.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646293(v=vs.85).aspx
Sorry that this doesn't directly answer your question, but I've grown quite fond of this tutorial for keyboard input.
http://www.gamedev.net/blog/355/entry-2250186-designing-a-robust-input-handling-system-for-games/
You should take a look.
This code will help to find KB_code value of every keyboard key
#include<iostream>
#include<conio.h>
using namespace std;
int main()
{
int KB_code=0;
while(1)
{
if (kbhit())
{
KB_code = getch();
cout<<"KB_code = "<<KB_code<<"\n";
}
}
return(0);
}

Need help correcting Access Violation with FFmpeg DLL

I'm trying to use the FFmpeg dll's using Visual Studio 2012 and I'm getting a run time access violation when I call avcodec_find_encoder. Here is the code:
// TestFFmpeg.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
extern "C" {
#include "libavcodec\avcodec.h"
#include "libavformat\avformat.h"
}
#define INBUF_SIZE 4096
int _tmain(int argc, _TCHAR* argv[])
{
AVCodec *codec;
const char *videoFilename = "C:\\Users\\Public\\Videos\\Sample Videos\\Wildlife.wmv";
av_register_all(); // This works; however, no parameters or return values.
codec = avcodec_find_encoder(CODEC_ID_WMV3); // Run time Access Violation HERE
if (!codec) {
fprintf(stderr, "Codec not found\n");
exit(1);
}
return 0;
}
Here is the error message:
Unhandled exception at 0x75C18B60 (msvcrt.dll) in TestFFmpeg.exe: 0xC0000005: Access violation reading location 0x00000049.
The stack trace is:
msvcrt.dll!_strcmp() Unknown
avcodec-54.dll!6a56caac() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for avcodec-54.dll]
> TestFFmpeg.exe!wmain(int argc, wchar_t * * argv) Line 23 C++
TestFFmpeg.exe!__tmainCRTStartup() Line 533 C
TestFFmpeg.exe!wmainCRTStartup() Line 377 C
kernel32.dll!#BaseThreadInitThunk#12() Unknown
ntdll.dll!___RtlUserThreadStart#8() Unknown
ntdll.dll!__RtlUserThreadStart#8() Unknown
I'm guessing there's a problem with returning the codec pointer, but I'm new to C++ and have no idea how to correct it. I tried the cdecl, stdcall, and fastcall calling conventions -- none corrected the issue. I'm using the latest 32-bit DLL from Zeranoe. Any suggestions?
EDIT:
I've called other functions in the DLL and they work. For example, avformat_open_input works properly. I can pass parameters and the function returns a successful return value (0) and populates the format context structure. av_find_stream_info works as well. I still can't figure out why avcodec_find_decoder creates an access violation.
Finally, fixed it. I did two steps and I'm not sure which one worked (heh):
Added the '.lib' files as linker input dependencies
I picked up the Sept 7 build and made sure I have all the same build-date for the dll's, libraries, and include files.
Everything appears to work fine now.