Development reference: Difference between revisions
No edit summary |
No edit summary |
||
(292 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
Design, programming and version control. | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Patterns | |||
|- | |||
| | |||
{| class="wikitable" | |||
! [[Major Objects]] | |||
|} | |||
{| class="wikitable" | |||
! [[Quick-http]] | |||
|} | |||
{| class="wikitable" | |||
! [[Continuous Integration]] | |||
|} | |||
{| class="wikitable" | |||
! [http://www.aosabook.org/en/index.html Architecture of major open source apps] | |||
|} | |||
{| class="wikitable" | |||
! [[Security]] | |||
|} | |||
{| class="wikitable" | |||
! [[Model View Controller]] | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! nosql enhances, not replaces, SQL | |||
|- | |||
| Not all data should be denormalized, and not all data should be normalized. The optimal mix considers the extent of the data. | |||
* Precise schemas are good when not overdone | |||
* When a container has an array with a large number of elements, it should be normalized | |||
* Sparse data and heterogeneous data are the best candidates for denormalization | |||
Postgres with JSON allows an elegant combination of nosql and SQL. | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Web design mantra | |||
|- | |||
| | |||
# DESIGN INPUT TO THE INPUT DEVICE | |||
## respect the input device | |||
## detect it and use a reasonable default guess | |||
## allow manual override | |||
## [mouse/pen]...[finger] | |||
## sm-md-lg ... sm-md-lg | |||
# DESIGN VISUALS TO THE SCREEN | |||
## high-res = SHOW LOTS OF DETAIL | |||
## responsive, zoomable | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! git central shared repository | |||
|- | |||
| Use bare repos for any central shared repositories. Use the [####.git] suffix on bare repo names. | |||
Bare repositories are designed to be shared. Maintenance on the central server is easier because you don't have local files to manage permissions or constant flux. Plus, you can always have a second repo on the central server where you check out a specific branch (e.g. to serve up with apache). If you want a dynamically updated central repo, clone the ###.git repo to ###, and add a post-receive hook (see bitpost quick-http.git for a good example). | |||
To configure the repo as shared: | |||
git config core.sharedRepository true | |||
To set it on a new git repo during initial setup, make sure devs are in the same group, and use: | |||
git init --shared=group | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Occam's razor | |||
|- | |||
| Among competing hypotheses, the one with the fewest assumptions should be selected. | |||
|} | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! C++ | |||
|- | |||
| | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Deleting multiple elements in a collection | |||
|- | |||
| | |||
* For sequences (vector, list...), best practice is to use the [https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom erase-remove] STL pattern | |||
* For associative containers (set, map...): just recurse and remove iterators, they won't muck up the sequence. [http://stackoverflow.com/questions/800955/remove-if-equivalent-for-stdmap example] | |||
See MemoryModel::saveDirtyObjectsAsNeeded() for example code. | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! c++ Create a portable C/C++ project | |||
|- | |||
| Use QtCreator + CMake, both available everywhere! | |||
set up: | |||
create a Qt project as: New Project-> Non-Qt/Plain C Project (CMake Build) | |||
pick the PARENT and use the name of the existing folder | |||
set up a build folder in the existing folder, called (base)/qtcreator-release-build | |||
it creates CMakeLists.txt (THIS IS BASICALLY THE PROJECT FILE!) | |||
also creates main.c or something | |||
build it! make sure it works | |||
NOW we can edit CMakeLists.txt - change . to ./src to get it to scan the src folder for code! | |||
and easily add "known" libs! this was all i needed: | |||
TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread websockets) | |||
make sure it builds | |||
now we want a DEBUG build as well! | |||
Projects->Build&Run->pick Build in weird Build/Run pillbox->Edit build configs: | |||
Rename: release | |||
CMake build dir: Make sure build dir is set to release ie qtcreator-debug-build | |||
Add: Clone: release, name: debug | |||
for debug, add a custom build step BEFORE make step: | |||
command: /usr/bin/cmake | |||
args: -DCMAKE_BUILD_TYPE=Debug . | |||
working dir: %{buildDir} | |||
(add it, and move it up above make) | |||
(build em both) | |||
Projects->Build&Run->pick Run in weird Build/Run pillbox | |||
Run Configuration: rename to "{...} release" | |||
clone it into "{...} debug" | |||
change working dir to match Build path | |||
change any needed params | |||
Now you should have build+run debug+release configurations, selectable in the weird project icon in bottom of left-side toolbar ("mode selector") | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! c++ in-memory storage of "major" objects | |||
|- | |||
| | |||
OBSERVATION ONE | |||
Consider An Important Qt Design: QObjects cannot normally be copied | |||
their copy constructors and assignment operators are private | |||
why? A Qt Object... | |||
might have a unique QObject::objectName(). If we copy a Qt Object, what name should we give the copy? | |||
has a location in an object hierarchy. If we copy a Qt Object, where should the copy be located? | |||
can be connected to other Qt Objects to emit signals to them or to receive signals emitted by them. If we copy a Qt Object, how should we transfer these connections to the copy? | |||
can have new properties added to it at runtime that are not declared in the C++ class. If we copy a Qt Object, should the copy include the properties that were added to the original? | |||
in other words, a QObject is a pretty serious object that has the ability to be tied to other objects and resources in ways that make copying dangerous | |||
isn't this true of all serious objects? pretty much | |||
OBSERVATION TWO | |||
if you have a vector of objects, you often want to track them individually outside the vector | |||
if you use a vector of pointers, you can move the object around much more cheaply, and not worry about costly large vector reallocations | |||
a vector of objects (not pointers) only makes sense if the number of objects is initially known and does not change over time | |||
OBSERVATION THREE | |||
STL vectors can store your pointers, iterate thru them, etc. | |||
for a vector of any substantial size, you want to keep objects sorted so you can find them quickly | |||
that's what my sorted_vector class is for; it simply bolts vector together with sort calls and a b_sorted status | |||
following STL practices, to get sorting, you have to provide operator< for whatever is in your vector | |||
BUT... you are not allowed to do operator<(const MyObjectPtr* right) because it would require a reference to a pointer which is not allowed | |||
BUT... you can provide a FUNCTOR to do the job, then provide it when sorting/searching | |||
a functor is basically a structure with a bool operator()(const MyObjectPtr* left, const MyObjectPtr* right) | |||
OBSERVATION FOUR | |||
unordered_set works even better when combining frequent CRUD with frequent lookups | |||
SUMMARY | |||
Dealing with tons of objects is par for the course in any significant app. | |||
Finding a needle in the haystack of those objects is also standard fare. | |||
Having multiple indices into those objects is also essential. | |||
Using unordered_set with object pointers and is very powerful. | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! c++ stl reverse iterator skeleton | |||
|- | |||
| From [http://www.sgi.com/tech/stl/ReverseIterator.html SGI]... | |||
reverse_iterator rfirst(V.end()); | |||
reverse_iterator rlast(V.begin()); | |||
while (rfirst != rlast) | |||
{ | |||
cout << *rfirst << endl; | |||
... | |||
rfirst++; | |||
} | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! c++ stl reading a binary file into a string | |||
|- | |||
| | |||
std::ifstream in("my.zip",std::ios::binary); | |||
if (!in) | |||
{ | |||
std::cout << "problem with file open" << std::endl; | |||
return 0; | |||
} | |||
in.seekg(0,std::ios::end); | |||
unsigned long length = in.tellg(); | |||
in.seekg(0,std::ios::beg); | |||
string str(length,0); | |||
std::copy( | |||
std::istreambuf_iterator< char >(in) , | |||
std::istreambuf_iterator< char >() , | |||
str.begin() | |||
); | |||
For more, see [[Reading a binary file|c++ stl reading a binary file]] | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! C/C++ best-in-class tool selection | |||
|- | |||
| I need to have easy setup of debug-level tool support for portable C++11 code. And I need to decide and stick to it to be efficient. | |||
* '''Compiler selection''' | |||
** linux and mac: gcc | |||
** windows: Visual Studio | |||
* '''IDE selection''' | |||
** linux and mac: Qt Creator | |||
** windows: Qt Creator (OR Visual Studio OR eclipse?) | |||
* '''Debugger selection''' | |||
** linux and mac: Qt Creator | |||
** windows: Qt Creator (OR Visual Studio OR eclipse?) | |||
|} | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! c++11 | |||
|- | |||
| | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! c++11 include base constructor (etc) in derived class | |||
|- | |||
| The awesome C++11 way to steal the constructor from the base class, oh man I've been waiting for this one... | |||
class HttpsServer : public Server<HTTPS> | |||
{ | |||
// DOES THIS FOR YOU! | |||
/* | |||
HttpsServer(unsigned short port, size_t num_threads, const std::string& cert_file, const std::string& private_key_file) | |||
: | |||
// Call base class | |||
Server<HTTPS>::Server(port, num_threads, cert_file, private_key_file) | |||
{} | |||
*/ | |||
using Server<HTTPS>::Server; | |||
.... | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! c++11 containers | ! c++11 containers | ||
|- | |- | ||
| sorted_vector || use when doing lots of unsorted insertions and maintaining constant sort would be expensive; | | sorted_vector || use when doing lots of unsorted insertions and maintaining constant sort would be expensive; vector is good for a big pile of things that only occasionally needs a sorted lookup | ||
|- | |- | ||
| map || sorted binary search tree; always sorted by key; you can walk through in sorted order (choose unordered if not needed!) | | map || sorted binary search tree; always sorted by key; you can walk through in sorted order (choose unordered if not needed!) | ||
|- | |- | ||
| multimap || same as map but allows dupe keys (not common) | | multimap || same as map but allows dupe keys (not as common) | ||
|- | |- | ||
| unordered_map || hashmap; always sorted by key; additional bucket required for hash collisions; no defined order when walking through | | unordered_map || hashmap; always sorted by key; additional bucket required for hash collisions; no defined order when walking through | ||
Line 16: | Line 260: | ||
You can use mutable on the variables that are not part of the key to remove the const.<br /> | You can use mutable on the variables that are not part of the key to remove the const.<br /> | ||
This changes the constness of the object from binary (completely const) to logical (constness is defined by the developer).<br /> | This changes the constness of the object from binary (completely const) to logical (constness is defined by the developer).<br /> | ||
So... set is | So... set is a good way to achieve both encapsulation and logical const - make const work for you, not against! :-)<br /> | ||
|- | |||
| set (etc.) of pointers || sets of pointers are the pinnacle of object stores<br /> | |||
The entire object can be dereferenced and accessed then without const issues.<br /> | The entire object can be dereferenced and accessed then without const issues.<br /> | ||
A pointer functor can be provided that does a sort by dereferencing the pointer to the object.<br /> | |||
Two requirements: you must make sure yourself that you do not change the key values - you can mark them const, provided in constructor;<br /> | Two requirements: you must make sure yourself that you do not change the key values - you can mark them const, provided in constructor;<br /> | ||
you must create sort functors that dereference the pointers to | you must create sort/equal/hash functors that dereference the pointers to use object contents<br /> | ||
(the default | (the default will be by pointer address).<br /> | ||
The arguably biggest advantage, as a result, is that you can create multiple sets<br /> | The arguably biggest advantage, as a result, is that you can create multiple sets<br /> | ||
to reference the same group of objects with different sort funtors to create multiple indices.<br /> | to reference the same group of objects with different sort funtors to create multiple indices.<br /> | ||
You just have to manage the keys carefully, so that they don't change (which would invalidate the sorting).<br /> | You just have to manage the keys carefully, so that they don't change (which would invalidate the sorting).<br /> | ||
The primary container can manage object allocation; using a heap-based unique_ptr allocation<br /> | |||
map vs key redux | |||
use a key in the set, derive a class from it with the contents | |||
+ small key | |||
+ encapsulation | |||
- requires mutable to solve the const problem | |||
use a key in the set, key includes a mutable object | |||
+ encapsulation | |||
- weird bc everything uses a const object but we have const functions like save() that change the mutable subobject | |||
use a map | |||
+ small key | |||
- no encapsulation, have to deal with a pair instead of an object | |||
can we just put a ref to key in the value? sure why not - err, bc we don't have access to it | |||
+ solves const problem bc value is totally mutable by design | |||
+ we can have multiple keys - and the value can have multiple refs to them | |||
+ simpler equal and hash functions | |||
map: | |||
create an object with internal key(s) | |||
create map index(es) with duplicate key values outside the object - dupe data is the downside | |||
use set(s) with one static key for find(): | |||
create an object with internal key(s) | |||
create set index(es) with specific hash/equals functor(s) | |||
when finding, use one static key object (even across indexes!) so there isn't a big construction each time; just set the necessary key values | |||
that proves difficult when dealing with member vars that are references | |||
but to solve it, just set up a structure of dummy static key objects that use each other; then provide a function to setKey(Object& keyref) { keyref_ = keyref; } | |||
nope, can't reassign refs | |||
the solution: use pointers not references | |||
yes that's right | |||
just do it | |||
apparently there was a reason i was anti-reference for all those years | |||
two reasons to use pointers: | |||
dynamically allocated | |||
reassignment required | |||
there ya go. simple. get it done. | |||
when accessing find results from the set, use a const_cast on the object! | |||
WARNING: a separate base class with the key sounds good... but fails when you have more than one index on the object. just use a static key object for them all! | |||
|} | |} | ||
Line 84: | Line 367: | ||
}; | }; | ||
typedef set<MyObject*,myobject_sort_by_id_functor> MyObjectsById; | typedef set<MyObject*,myobject_sort_by_id_functor> MyObjectsById; | ||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! c++11 loop through vector to erase some items | |||
|- | |||
| Note that other containers' iterators may not be invalidated so you can just erase() as needed... | |||
For vectors, you have to play with iterators to get it right - watch for proper ++ pre/postfix! | |||
for (it = numbers.begin(); it != numbers.end(); ) // NOTE we increment below, only if we don't erase | |||
{ | |||
if (*it.no_good()) | |||
{ | |||
numbers.erase(it++); // NOTE that we ERASE THEN INCREMENT here. | |||
} | |||
else | |||
{ | |||
++it; | |||
} | |||
} | |||
I thought I had always looped backwards to do this, I *think* that's ok too, but I don't see it used in my code, I think I'll avoid. :-) | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! c++11 range based for loop, jacked with boost index if needed | |||
|- | |||
| No iterator usage at all. Nice at times, not enough at others. Make SURE to always use a reference or you will be working on a COPY. Make it const if you aren't changing the object. | |||
for (auto& mc : my_container) | |||
mc.setString("default"); | |||
for (const auto& cmc : my_container) | |||
cout << cmc.asString(); | |||
boost index can give you the index if you need it, sweet: | |||
#include <boost/range/adaptor/indexed.hpp> | |||
... | |||
for (const auto &element: boost::adaptors::index(mah_container)) | |||
cout << element.value() << element.index(); | |||
|} | |} | ||
Line 145: | Line 462: | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! C++11 scoped enumeration | ||
|- | |- | ||
| C++11 has scoped enumeration, which lets you specify the SPECIFIC VARIABLE TYPE for the enum. Perfect, let's use uint_fast32_t. | |||
enum class STRING_PREF_INDEX int_fast32_t: { ... }; | |||
Unfortunately, gcc gives me a scary warning, and stuff fails. For some reason, it does not know about the provided type, although it is definitely defined. Revisit this later if you have time. | |||
warning: elaborated-type-specifier for a scoped enum must not use the ‘class’ keyword | |||
Old skool is still cool: | |||
typedef enum | |||
{ | |||
// assert( SP_COUNT == 2 ); | |||
SP_FIRST = 0 , | |||
SP_SOME_PREF = SP_FIRST , | |||
SP_ANOTHA , | |||
SP_COUNT | |||
} STRING_PREF_INDEX; | |||
|} | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! boost | |||
|- | |||
| | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! boost release and debug build for linux | |||
|- | |||
| | |||
# download latest boost, eg: boost_1_59_0 | |||
m@wallee:~/development$ 7z x boost_1_59_0.7z | |||
rm boost && ln -s boost_1_59 boost | |||
cd boost | |||
build_boost_release_and_debug.sh | |||
# IMPORTANT: then patch .bashrc as instructed | |||
# cmake-###/clean.sh and cmake-###/build.sh are customized to match | |||
# (and older eclipse and server/nix/bootstrap.sh) | |||
To upgrade a CMake project: | |||
cd cmake-###/ | |||
./clean.sh | |||
./build.sh | |||
To upgrade an older autotools project: | |||
cd nix | |||
make distclean # removes nasty .deps folders that link to old boost if you let them | |||
make clean # removes .o files etc | |||
cd ../build-Release && make distclean && make clean | |||
cd ../build-Debug && make distclean && make clean | |||
cd .. | |||
./bootstrap force release | |||
./bootstrap force debug | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! boost release and debug build for Windows | |||
|- | |||
| Open a VS2015 x64 Native Tools Command Prompt. | |||
EITHER: for new installs, you have to run bootstrap.bat first, it will build b2; | |||
OR: for reruns, remove boost dirs: [bin.v2, stage]. | |||
Then build 64-bit: | |||
cd "....\boost_1_59_0" | |||
b2 toolset=msvc variant=release,debug link=static address-model=64 | |||
rem trying to avoid excessive options, assuming I don't need these: threading=multi | |||
(old stuff) | |||
--toolset=msvc-14.0 address-model=64 --build-type=complete --stagedir=windows_lib\x64 stage | |||
Now open VS2013 x86 Native Tools Command Prompt and build 32-bit: | |||
cd "C:\Michael's Data\development\sixth_column\boost_1_55_0" | |||
bjam --toolset=msvc-12.0 address-model=32 --build-type=complete --stagedir=windows_lib\x86 stage | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! boost regex (very similar to c++11, with LESS BUGS and MORE POWER) | |||
|- | |||
| boost regex does everything you could need, take your time to get it right | |||
* regex_search will work hard to find substrings, while regex_match requires your regex to match entire input | |||
* smatch is a great way to get back a bunch of iterators to the results | |||
example: | |||
virtual bool url_upgrade_any_old_semver(string& url) | |||
{ | |||
// Perform a regex to update the embedded version if needed. | |||
// We have to see if (1) we have a semver and (2) it is not the current semver. | |||
// Only then do we take action. | |||
boost::regex regex("/([v0-9.]+?)/(.*)"); | |||
boost::smatch sm_res; | |||
if (boost::regex_match(url,sm_res,regex,boost::match_default)) | |||
{ | |||
string incoming_semver(sm_res[1].first,sm_res[1].second); | |||
if (incoming_semver != semanticVersion()) | |||
{ | |||
url = string("/")+semanticVersion()+"/"+string(sm_res[2].first,sm_res[2].second); | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
results: | |||
original string: string(sm_res[0].first,sm_res[0].second); | |||
first group: string(sm_res[1].first,sm_res[1].second); | |||
second group: string(sm_res[2].first,sm_res[2].second); | |||
etc. | |||
|} | |||
|} | |} | ||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! C++ libraries | |||
|- | |||
| | |||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! String escape formatting across different languages and systems | ||
|- | |- | ||
| | | | ||
* c++ to JSON: always use nlohmann::json j.dump() to encode, to ensure strings are properly escaped | |||
* JSON to c++: always use nlohmann::json j.parse() " | |||
* c++ to Javascript: use raw_to_Javascript() to properly escape | |||
* c++ to sqlite: use SqliteLocalModel::safestr(), which uses double_doublequotes(str) | |||
|} | |||
[[Postgres]] | |||
[[Simple-Web-Server]] | |||
[[Robot Operating System]] | |||
[[C++ https libraries]] | |||
[[Configure Qt development on Windows + Mac + linux]] | |||
[[Build the TagLib library with Visual Studio 2013]] | |||
|} | |} | ||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! C/C++ building/linking | |||
|- | |||
| | |||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! gcc makefile pain | ||
|- | |- | ||
| | | | ||
* I went through a LOT of pain to determine that gcc requires libraries to be listed AFTER the source and output parameters | |||
* set LD_LIBRARY_PATH to point to your libs if they are not in system location | |||
* Make sure Makefile uses TABS NOT SPACES. it's a FACT OF LIFE. hate it if you want. plenty more things to hate about linux/C as well. | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! gcc install multiple versions in ubuntu (4 and 5 in wily, eg) | |||
|- | |||
| My code will not compile with gcc 5, the version provided with Ubuntu wily. | |||
It gives warnings like this: | |||
/home/m/development/boost_1_59_0/boost/smart_ptr/shared_ptr.hpp:547:34: warning: ‘template<class> class std::auto_ptr’ is deprecated [-Wdeprecated-declarations] | |||
and outright errors like this: | |||
depbase=`echo AtServer.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\ | |||
g++ -DPACKAGE_NAME=\"at_server\" -DPACKAGE_TARNAME=\"at_server\" -DPACKAGE_VERSION=\"1.0\" -DPACKAGE_STRING=\"at_server\ 1.0\" -DPACKAGE_BUGREPORT=\"m@abettersoftware.com\" -DPACKAGE_URL=\"\" -DPACKAGE=\"at_server\" -DVERSION=\"1.0\" -I. -I../../src -I/home/m/development/Reusable/c++ -I/home/m/development/Reusable/c++/sqlite -std=c++11 -I/home/m/development/boost_1_59_0 -ggdb3 -O0 -std=c++11 -MT AtServer.o -MD -MP -MF $depbase.Tpo -c -o AtServer.o ../../src/AtServer.cpp &&\ | |||
mv -f $depbase.Tpo $depbase.Po | |||
In file included from /usr/include/c++/5/bits/stl_algo.h:60:0, | |||
from /usr/include/c++/5/algorithm:62, | |||
from /usr/include/c++/5/ext/slist:47, | |||
from /home/m/development/boost_1_59_0/boost/algorithm/string/std/slist_traits.hpp:16, | |||
from /home/m/development/boost_1_59_0/boost/algorithm/string/std_containers_traits.hpp:23, | |||
from /home/m/development/boost_1_59_0/boost/algorithm/string.hpp:18, | |||
from /home/m/development/Reusable/c++/utilities.hpp:4, | |||
from ../../src/MemoryModel.hpp:11, | |||
from ../../src/SqliteLocalModel.hpp:13, | |||
from ../../src/AtServer.cpp:70: | |||
/usr/include/c++/5/bits/algorithmfwd.h:573:13: error: initializer provided for function | |||
noexcept(__and_<is_nothrow_move_constructible<_Tp>, | |||
^ | |||
/usr/include/c++/5/bits/algorithmfwd.h:582:13: error: initializer provided for function | |||
noexcept(noexcept(swap(*__a, *__b))) | |||
You can set up the update-alternatives tool to switch out the symlinks: | |||
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.9 | |||
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 20 --slave /usr/bin/g++ g++ /usr/bin/g++-5 | |||
BUT that seems BAD to me to switch out the compiler used by the SYSTEM. Instead, we should specify the compiler required by the PROJECT. This is supposed to do it, but it still uses /usr/include/c++/5, which seems wrong, and gives me errors: | |||
CC=gcc-4.9 | |||
|} | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[git]] | |||
|} | |} | ||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Debugging | |||
|- | |||
| | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Chrome capture large JSON variable | |||
|- | |||
| This is just pointlessly bizarre: | |||
* hit a breakpoint in the chrome debugger | |||
* right-click a variable and say "copy to global variable" (console will show name, typically "temp1") | |||
* push the variable to the clipboard by typing this in the console: | |||
copy(temp1) | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Visual Studio Code capture large string variable | |||
|- | |||
| While debugging, you can use the Debug Console to print memory, including the content of strings that are clipped by default in the variables and watch windows. | |||
View > Open View > Debug Console | |||
From there, send gdb a command to print memory – 300 characters of a string in this example: | |||
-exec x/300sb Query.c_str() | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Qt Creator conditional breakpoint | |||
|- | |||
| To break on line number with string condition: | |||
* Set the breakpoint on the line as usual: F9 or click in left border | |||
* In the breakpoints list, rclick Edit | |||
* Add a condition; to break on a string value, THIS WORKS: | |||
((int)strcmp(strSymbol.c_str(), "GMO")) == 0 | |||
* BUT THERE IS A PRICE TO PAY. qt/gcc won't continue properly, unless you sset ANOTHER common breakpoint, hit it, and resume from that. It appears gcc continues (we hit the breakpoint after all), but qt does no logging or debugging, bah | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Qt Creator and linux debug libraries | |||
|- | |||
| | |||
* I was able to build lws in debug, install in /usr/local, then I could step right into its code | |||
m@case:~/development/causam/git/np/nop-bigress-client-c$ ./build_lws_debug | |||
Install the project... | |||
-- Install configuration: "DEBUG" | |||
-- Installing: /usr/local/lib/pkgconfig/libwebsockets.pc | |||
-- Installing: /usr/local/lib/libwebsockets.a | |||
-- Up-to-date: /usr/local/include/libwebsockets.h | |||
(etc) | |||
* Signals: At some point I needed to force gdb to pass SIGINT, SIGPIPE... signals to the app instead of gdb, after ssl kept causing Qt to pop a message and break in the debugger. To do so: | |||
Qt Creator->Options->Debugger-> | |||
[ ] Show a message box when receiving a signal | |||
Debugger Helper Customization: handle SIGPIPE pass nostop noprint | |||
* You should be able to install debug builds of libraries into /usr/local (as mentioned above). Older notes if you can't get that going: To debug into an included library that is not installed system-wide: | |||
use Tools->Options->General->Source Paths Map | |||
source: /home/m/development/causam/git/nop-bigress-client-c/cmake-debug | |||
that's the COMPLETE PATH TO DEBUG EXE | |||
target: /home/m/development/causam/git/libwebsockets-master/lib | |||
at first i thought this would work: /usr/local/lib | |||
but i did a static build so i needed teh actual exe! COOL | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! QT Creator valgrind EASY | |||
|- | |||
| Valgrind is easy to use. Just find debugger pane top-left dropdown, switch mode from Debugger to Memcheck, and restart debugger. | |||
|} | |||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! c/c++ gdb debugging | ! c/c++ gdb debugging | ||
Line 243: | Line 748: | ||
| ddd gives you a front end. I need to use it more, compare to other options | | ddd gives you a front end. I need to use it more, compare to other options | ||
|} | |} | ||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! C | |||
|- | |||
| | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Library handling in linux | |||
|- | |||
| gcc library basics (good to know for autotools and CMake too) | |||
* The gcc -l command line option specifies a specific library NAME. It will add the rest to give you (eg) lib[NAME].a | |||
* Specify the library search path with the -L option. Things that you as a user install seem to default to /usr/local/lib | |||
* This will link myprogram with the static library libfoo.a in the folder /home/me/foo/lib. | |||
gcc -o myprogram -lfoo -L/home/me/foo/lib myprogram.c | |||
Tools to check library dependencies: | |||
* ldd [executable] | |||
* objdump -p /path/to/program | grep NEEDED | |||
* objdump -x [object.so] | |||
* readelf -d [exe] | |||
* sudo pldd <PID> | |||
* sudo pmap <PID> | |||
|} | |||
[[Cross Compiling]] | |||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
Line 260: | Line 796: | ||
|} | |} | ||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Javascript]] | |||
|}<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Node.js]] | |||
|}<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[React]] | |||
|}<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Vite]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[JSON]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[HTML]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[CSS]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! SQL | ||
|- | |- | ||
| | | | ||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! Count records within a range | |||
|- | |||
| This groups records into ranges, sorts by them, and gives a count, sweet: | |||
select count(*), id/1000000 as groupid from AccountHistory group by groupid; | |||
|} | |||
[[postgres]] - [[sqlite]] - [[mysql]] - [[SQL Server]] - [[Robo 3T]] - [[DBeaver]] - [[pgadmin4]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Meteor]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Android]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Arduino]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Raspberry Pi]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[iOS]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[.NET Core]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Java]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Kotlin]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Maven]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Scala]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Python]] | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Go]] | |||
|} | |} | ||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! PHP | ||
|- | |- | ||
| | | | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! php debugging | ! php debugging | ||
Line 317: | Line 1,024: | ||
/etc/init.d/apache restart | /etc/init.d/apache restart | ||
|} | |} | ||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="wikitable" | |||
! [[Bash basics]] but please prefer node or python :-) | |||
|} | |||
<!-- | |||
=========================================================================================================================================================================================================================================================================================== | |||
--> | |||
{| class="mw-collapsible mw-collapsed wikitable" | |||
! misc | |||
|- | |||
| | |||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! SVN repo move across servers | ||
|- | |- | ||
| | |||
* use a tool like VisualSVN to stop SVN server | |||
* copy the repo's entire svn server directory, eg: c:\svn\Software | |||
* copy it into the new server under a unique name, eg: c:\svn\NewSoftware | |||
* use a tool like VisualSVN to restart SVN server | |||
You should now have the new code, accessible as usual from svn. | |||
NOTE from Tom: If you move code around, make sure you tag it, then copy the tag, to preserve history (as opposed to directly moving the folder). Weird but true. | |||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! SQL Server 2008+ proper upsert using MERGE | ! SQL Server 2008+ proper upsert using MERGE | ||
Line 373: | Line 1,103: | ||
); | ); | ||
|} | |} | ||
{| class="wikitable" | {| class="wikitable" | ||
! [[Web Services]] | ! [[Web Services]] | ||
Line 397: | Line 1,110: | ||
! [[Firefox Addon development]] | ! [[Firefox Addon development]] | ||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! c++ Create a portable autotools C++ project in linux | ||
|- | |- | ||
| | | (OLD, USE CMAKE NOW) | ||
For anything serious, it's best to clone an existing project's skeleton. | |||
* main.cpp | |||
* MVC code | |||
* nix/copy_from folder | |||
* make sure .bashrc is configured for boost | |||
* nix$ bootstrap_autotools_project.sh force release debug | |||
* set up eclipse according to screenshots in [[Eclipse]] | |||
|} | |} | ||
{| class="mw-collapsible mw-collapsed wikitable" | {| class="mw-collapsible mw-collapsed wikitable" | ||
! | ! c++ Create a portable C++ project in Visual Studio | ||
|- | |- | ||
| | | (OLD, USE CMAKE NOW) | ||
If you don't have existing code, it's probably best to create a project_name.cpp file with your main() function. | |||
int main( int argc, char * argv[] ) | |||
{ | |||
return 0; | |||
} | |||
Then in Visual Studio... | |||
File->New->Project from existing code | |||
C++ | |||
( | (then use mostly defaults on this page, once you provide file location and project name) | ||
Project file location: <base>\project_name | |||
Project name: project_name | |||
[x] Add files from these folders | |||
Add subs | |||
[x] <base>\project_name | |||
NEXT | |||
Use Visual Studio | |||
Console application project | |||
No ATL, MFC, CLR | |||
NEXT | |||
NEXT | |||
FINISH | |||
Then add Reusable and boost include and lib paths: | |||
Example if you built boost according to notes below: | |||
Project->Properties->All Configurations->Configuration Properties->VC++ Directories->Include Directories-> | |||
$(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\Reusable\c++ | |||
INCLUDE: C:\Software Development\boost_1_53_0 | |||
LIB: C:\Software Development\boost_1_53_0\stage\lib | |||
|} | |||
|} | |} |
Latest revision as of 23:15, 25 November 2023
Design, programming and version control.
Patterns | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
C++ | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
c++11 | |||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
boost | ||||||
---|---|---|---|---|---|---|
|
C++ libraries | ||
---|---|---|
|
C/C++ building/linking | ||||
---|---|---|---|---|
|
git |
---|
Debugging | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
C | ||||
---|---|---|---|---|
|
Javascript |
---|
Node.js |
---|
React |
---|
Vite |
---|
JSON |
---|
HTML |
---|
CSS |
---|
SQL | ||
---|---|---|
postgres - sqlite - mysql - SQL Server - Robo 3T - DBeaver - pgadmin4 |
Meteor |
---|
Android |
---|
Arduino |
---|
Raspberry Pi |
---|
iOS |
---|
.NET Core |
---|
Java |
---|
Kotlin |
---|
Maven |
---|
Scala |
---|
Python |
---|
Go |
---|
PHP | |||
---|---|---|---|
|
Bash basics but please prefer node or python :-) |
---|
misc | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|