<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-4168503339888369834</atom:id><lastBuildDate>Wed, 27 Apr 2022 22:42:24 +0000</lastBuildDate><category>lisp</category><category>c++</category><category>boost</category><category>qt</category><category>personal</category><category>weblocks</category><category>strictlybusiness</category><category>buildingsoftware</category><category>emacs</category><category>python</category><category>30day</category><category>boostcon</category><category>scons</category><category>serialization</category><category>subversion</category><category>build</category><category>business</category><category>c++0x</category><category>cl-selenium</category><category>cl-who</category><category>clsql</category><category>computers</category><category>gui</category><category>hunchentoot</category><category>meta</category><category>source control</category><category>ubuntu</category><category>afk</category><category>ajax</category><category>asdf</category><category>bitcoin</category><category>bjam</category><category>broken</category><category>bzr</category><category>c++1x</category><category>cl-opengl</category><category>clang</category><category>clbuild</category><category>code</category><category>deepinthought</category><category>dependencyinjection</category><category>development</category><category>di</category><category>docbook</category><category>dontreadme</category><category>factor</category><category>futurereference</category><category>git</category><category>google</category><category>government</category><category>gtk</category><category>gtkmm</category><category>i&#39;m on the list now</category><category>java</category><category>lambda</category><category>linux</category><category>mercurial</category><category>mfc465-cn</category><category>money</category><category>ninja</category><category>notaloser</category><category>nothingtoseehere</category><category>nvidia</category><category>opengl</category><category>parenscript</category><category>psa</category><category>quit</category><category>rant</category><category>research</category><category>rxvt</category><category>sbcl</category><category>slime</category><category>soapbox</category><category>software</category><category>spam?</category><category>svk</category><category>svn</category><category>testing</category><category>tr1</category><category>vancpp</category><category>wla</category><category>wtf</category><title>sizeof(uint32t)</title><description>Dodheim reads only four blogs. This is one of them.</description><link>http://uint32t.blogspot.com/</link><managingEditor>noreply@blogger.com (Unknown)</managingEditor><generator>Blogger</generator><openSearch:totalResults>128</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-7711055707210930792</guid><pubDate>Wed, 16 Feb 2022 05:56:00 +0000</pubDate><atom:updated>2022-02-16T00:58:23.644-05:00</atom:updated><title>Does it get much worse than this</title><description>&lt;p&gt;&lt;span face=&quot;&amp;quot;Trebuchet MS&amp;quot;, Trebuchet, Verdana, sans-serif&quot; style=&quot;background-color: white; font-size: 14.4px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEj_zG0TwJ5xQvhEgQhPkUtfCvwDuFQ5p3LzO_1sFrpezaAAs_Nd-ypWmPZdqtw8eDZ6gFRBMDIrCVus1F7k0jUfPLjfoGjRkwdJspN0FUCd8Ncyht4YB_pEKk-LU9nqGX293lomFUcgYusAt3mJwMou3sPAo8DcRCI4gXWgvx2X6KSliurddVuo0QbUnQ&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;189&quot; data-original-width=&quot;885&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEj_zG0TwJ5xQvhEgQhPkUtfCvwDuFQ5p3LzO_1sFrpezaAAs_Nd-ypWmPZdqtw8eDZ6gFRBMDIrCVus1F7k0jUfPLjfoGjRkwdJspN0FUCd8Ncyht4YB_pEKk-LU9nqGX293lomFUcgYusAt3mJwMou3sPAo8DcRCI4gXWgvx2X6KSliurddVuo0QbUnQ=s16000&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&amp;nbsp;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span face=&quot;&amp;quot;Trebuchet MS&amp;quot;, Trebuchet, Verdana, sans-serif&quot; style=&quot;background-color: white; font-size: 14.4px;&quot;&gt;October 26, 2021:&amp;nbsp;&lt;a href=&quot;https://uint32t.blogspot.com/2021/10/the-future.html&quot;&gt;The cultural elites driving this lock down will be caught off guard as they were caught off guard by he-who-shall-not-be-named. As with anyone losing power, they will try to increase their grip. It will be bad.&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEjwnLQBkICPTAM-JxGp7OuYTqLvSuP2PX9_O6WwsdCjcjlHbGSsFkX7UX86c9-9NGTKfhrGwmaQH9LLW6cWEjRB770_lyU0QtGrrTsbdJcvS6nNtOmHTQ_diJ9m-Faab_GQUn6QhgWLt_4fICkxPuEIrGQdwkYJ2EEuNAjHa792KbQD1YXMe7rTj34NZQ&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;860&quot; data-original-width=&quot;1150&quot; height=&quot;299&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEjwnLQBkICPTAM-JxGp7OuYTqLvSuP2PX9_O6WwsdCjcjlHbGSsFkX7UX86c9-9NGTKfhrGwmaQH9LLW6cWEjRB770_lyU0QtGrrTsbdJcvS6nNtOmHTQ_diJ9m-Faab_GQUn6QhgWLt_4fICkxPuEIrGQdwkYJ2EEuNAjHa792KbQD1YXMe7rTj34NZQ=w400-h299&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;a href=&quot;https://uint32t.blogspot.com/2022/01/whats-next-and-apology.html&quot; target=&quot;_blank&quot;&gt;So if the protests can be quashed without losing moral authority, and maintaining power, that gives the elite the confirmation that they do indeed have very strong control over much of the world economy. And as said in a previous post, they are very much happy with the fact that they get along well together.&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;br style=&quot;background-color: white; font-family: &amp;quot;Trebuchet MS&amp;quot;, Trebuchet, Verdana, sans-serif; font-size: 14.4px;&quot; /&gt;&lt;/div&gt;&lt;div&gt;It seems they have lost the moral authority now. The federal government of Canada is being openly mocked worldwide by &lt;b&gt;private &lt;/b&gt;news media. Oligopoly/state-owned news media is carrying water for the aforementioned reason, that the self-styled elites who run things behind closed doors are very invested in the outcome in a major Western country. After Canada, USA is next. There is an intuitive understanding of this which is why so many in the US are invested in what is happening in Canada.&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;div&gt;&lt;a href=&quot;https://uint32t.blogspot.com/2021/10/the-future.html&quot; target=&quot;_blank&quot;&gt;But in the end, the people will refuse to participate and will develop the leverage needed to add the right checks and balances to a system that is sorely lacking them. I doubt it will be violent.&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;So far so good.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is a rumor that the PM of Canada attempted to get the military involved and they said no. It is a rumor, but...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;a href=&quot;https://uint32t.blogspot.com/2022/01/the-future-is-now.html&quot;&gt;Will the enforcers support the leaders if they require violence?&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://uint32t.blogspot.com/2022/01/the-future-is-now.html&quot;&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://uint32t.blogspot.com/2022/01/the-future-is-now.html&quot;&gt;I&#39;m not so sure.&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;There are also rumors that certain police forces are siding with protesters. I do not know how true this is.&amp;nbsp;&lt;/p&gt;&lt;p&gt;A famous psychologist has referred to the current PM as a teenage actor. If true, this means that his reactions are unpredictable and will be inward focused. A dangerous combination.&lt;/p&gt;&lt;p&gt;I&#39;d be worried, if it didn&#39;t seem that the federal government of Canada is grasping at straws to hold onto power (the &quot;It will be bad&quot; part of things) and the enforcers are perhaps refusing to intervene.&lt;/p&gt;&lt;p&gt;This isn&#39;t an attempt to consolidate power. This is an attempt to hold onto the last bit of power they have left. It looks the same, but has wildly different outcomes.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;</description><link>http://uint32t.blogspot.com/2022/02/does-it-get-much-worse-than-this.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEj_zG0TwJ5xQvhEgQhPkUtfCvwDuFQ5p3LzO_1sFrpezaAAs_Nd-ypWmPZdqtw8eDZ6gFRBMDIrCVus1F7k0jUfPLjfoGjRkwdJspN0FUCd8Ncyht4YB_pEKk-LU9nqGX293lomFUcgYusAt3mJwMou3sPAo8DcRCI4gXWgvx2X6KSliurddVuo0QbUnQ=s72-c" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-8360903100770073735</guid><pubDate>Fri, 11 Feb 2022 13:03:00 +0000</pubDate><atom:updated>2022-02-11T08:03:00.226-05:00</atom:updated><title>Excess performance and outcome independence</title><description>&lt;p&gt;Outperforming can be relative.&lt;/p&gt;&lt;p&gt;For example, someone raised in poverty achieves excess performance simply by moving to the middle class, having a retirement fund and a successful marriage.&lt;/p&gt;&lt;p&gt;In software development, excess performance falls under multiple potential categories:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Design&lt;/li&gt;&lt;li&gt;Implementation&lt;/li&gt;&lt;li&gt;Management&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;In business, excess performance is obvious assuming no shenanigans.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In many cases, it may be hard to quantify, but you know what it looks like when you see it because it stands out.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Many who outperform in various situations in life were coached into it as children and their &quot;excess performance&quot; actually does not exceed what other similar children would achieve. For example, if&amp;nbsp; one went to private schools, and their friends went to private schools and they all have similar careers, one did not out perform anyone.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In that case, it is more likely that the parents are those who outperformed, not the children, depending on the parents&#39; peer group.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What is excess performance as an adult that is independent of your background?&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Learn a new skill, and make more money doing it.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Career progression can be a form of excess performance. For example transitioning from individual contributor to CTO of a non-trivial company over a period of time.&lt;/li&gt;&lt;li&gt;Money is just a simple way to keep score. One might also take up painting and even selling 3-5K of paintings per year could be out performance (not that I would know!)&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Fix a long standing physical or mental health problem/breaking long standing habits&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Aside from the obvious, this can be things as simple as choosing the type of people you wish to be around.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div&gt;There are surely more examples, but successfully accomplishing either of those requires so much time that it is almost impossible to achieve as an adult.&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You need to make the time.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While aiming for excess performance is something everyone wants to do, in practical terms it is actually quite difficult and ugly. It&#39;s easier to just sit around and retain the status quo (there is nothing wrong with this, life satisfaction is very important.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But if someone is trying to exceed their station by one or two standard deviations, it requires an unrelenting focus.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Focusing on one thing will potentially mean letting other less important things fall off.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Do this consciously.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you achieve the excess performance that you sought, you know the things you lost were worth it. If you did not achieve the excess performance, and lost the less important things as well, you were already prepared.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By making this active decision, you are now outcome independent.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I am debating whether to talk in less vague terms about this, but perhaps another day.&lt;/div&gt;&lt;p&gt;&lt;/p&gt;</description><link>http://uint32t.blogspot.com/2022/02/excess-performance-and-outcome.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-7884318162690608875</guid><pubDate>Sat, 29 Jan 2022 14:00:00 +0000</pubDate><atom:updated>2022-01-29T09:00:00.244-05:00</atom:updated><title>What&#39;s next (and an apology)</title><description>&lt;p&gt;I apologize for making this blog political/personal recently. I know this is/was a tech blog and trust me, I have a ton of very cool tech stuff to write about (see&amp;nbsp;&lt;a href=&quot;https://github.com/sohailsomani&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;&amp;nbsp;for some stuff I&#39;ve been working on) and I will write about it again.&lt;/p&gt;&lt;p&gt;While Canada, the land mass is &quot;rich&quot;, the civilization is stagnating and part of this is an overreaching government bureaucracy that infects every aspect of our lives and makes too many people dependent through its largesse. Roughly 10% of the population is directly employed by the government which doesn&#39;t sound too bad, yet government spending is 50% of GDP. Out of the remaining 50%, half is housing related and commodity extraction. Note that I understand government spending can be beneficial to the economy. At these levels and the sectors, it is purely a jobs program. Housing prices in Canada are soon to be the biggest export. No, they are not going to do anything about it. So in effect, perhaps 60% of GDP is directly dependent on the government for growth.&lt;/p&gt;&lt;p&gt;This situation is not at all unique in the world. There are a cluster of currently stable countries with similar nominal GDP which share a similar economic and roughly similar government structure. Included in this list are France, Belgium, Sweden, Germany, Netherlands, UK, and Spain.&lt;/p&gt;&lt;p&gt;That could be why it was so easy for such countries to &quot;shut down&quot; and remain shut down as government is a large component of the economy and who is going to complain about being paid to stay home while their homes appreciate another 40%? Other countries could literally not afford to stay closed, and did not.&lt;/p&gt;&lt;p&gt;Through the pandemic response and economic policies, it&#39;s relatively easy to see that&amp;nbsp;such countries are fundamentally in decline and the pandemic is being used as an excuse to paper over it. See &lt;a href=&quot;https://www.principles.com/the-changing-world-order/&quot; target=&quot;_blank&quot;&gt;The Changing World Order&lt;/a&gt; by Ray Dalio for a great exposition. I also recommend his debt crises book. The US is apparently faring better in pockets, for example Florida and Texas are largely open without disproportionately negative pandemic outcomes while other states continue to occasionally &quot;lock down&quot;. China&#39;s &quot;zero COVID&quot; policy likely never worked, but we&#39;ll never know the truth.&lt;/p&gt;&lt;p&gt;I like to consider human civilization as an organism. If you&#39;ve ever watched traffic going in and out of a city over a period of a day, it&#39;s like an animal breathing and can be mesmerizing. As a result, I see the Canadian trucker protest, sizable or not, as a blister that has popped. Or a tumour that will grow. Which one it is, I don&#39;t know. Insert your favourite analogy here.&lt;/p&gt;&lt;p&gt;That being said.&lt;/p&gt;&lt;p&gt;&lt;b&gt;What is happening?&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Justin Trudeau has absconded and left Ottawa under the guise of quarantine. He is basically going to wait out the protests and is no doubt planning with other leaders on how to deal with the problem perhaps without having to give it the dignity of a formal response.&lt;/p&gt;&lt;p&gt;As in the previous couple of posts, I said they will try and increase their grip. Nova Scotia recently is &lt;a href=&quot;https://tnc.news/2022/01/28/nova-scotia-bans-gatherings-along-highway-in-support-of-trucker-freedom-convoy/&quot; target=&quot;_blank&quot;&gt;attempting to outlaw&lt;/a&gt; this specific form of protest. Expect Ontario/Ottawa to follow suit.&lt;/p&gt;&lt;p&gt;The key bit of this kind of legislation is they are making donating to the cause illegal as well. And given the Canadian Charter of Rights and Freedoms isn&#39;t anything but a polite suggestion, it is likely to be upheld on appeal.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Why truckers?&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I suspect this is mostly because truckers represent many productive and necessary parts of the economy, but also because they are mostly independent even indirectly, from the wealth of government. Side note: one of the most wealthy people I know runs trucking companies in multiple countries. It really is a purely capitalistic endeavour for the most part. The second most wealthy person I know has his &lt;b&gt;huge&lt;/b&gt;&amp;nbsp;business tied 80% to government.&lt;/p&gt;&lt;p&gt;&lt;b&gt;What is immediately next?&lt;/b&gt;&lt;/p&gt;&lt;p&gt;The logical conclusion of this is that the powers that be are setting the stage for violence but will initially attempt to extinguish whatever vigour exists through lack of media coverage and perhaps also preventing the trucks from entering Ottawa.&lt;/p&gt;&lt;p&gt;Trudeau has already signalled the basics of the government approach. They will wait it out and set the stage to apply force if needed. I am not sure how well organized this protest is, and how long they can hold out but this appears to be the approach.&lt;/p&gt;&lt;p&gt;The truckers on their end cannot leave Ottawa until mandates are lifted wholesale or they are forced out. The only way the truckers can remain in protest mode is if they have supplies going to the front lines. This is only possible if people continue to donate to the cause.&lt;/p&gt;&lt;p&gt;The truckers have to be prepared to become VERY uncomfortable.&lt;/p&gt;&lt;p&gt;When faced with protests, governments have 3 major responses:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Accede/negotiate&lt;/li&gt;&lt;li&gt;Ignore&lt;/li&gt;&lt;li&gt;Respond with violence&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;If the legislative response from Nova Scotia is to be enacted, and be replicated across the country, particularly in Ontario, then the state has chosen to set the stage for (3) as laws are enforced by violence. Hence why they are seeking to make funding the protest illegal.&lt;/p&gt;&lt;p&gt;Being in the cross hairs of the government enforcers is a very expensive proposition in all Western democracies even if you have done nothing wrong. Anyone donating to the cause will think thrice.&lt;/p&gt;&lt;p&gt;Therefore, laws preventing funding of the protest cut off the most important input into the effectiveness of a long term sit in type protest.&lt;/p&gt;&lt;p&gt;There is a very large chance that the funding platforms will say &quot;well, nothing we can do about it, the government made it illegal&quot; and cancel all funding raised.&lt;/p&gt;&lt;p&gt;There is a very small chance that the organizers will encourage people to donate via Monero which is a privacy preserving cryptocurrency, but it is a black swan that will change the entire circumstances of the protest. The government may make such crypto illegal as a result.&lt;/p&gt;&lt;p&gt;In summary:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;The government has chosen violence, it just hasn&#39;t applied it yet&lt;/li&gt;&lt;li&gt;The truckers funding is likely to be cut off&lt;/li&gt;&lt;li&gt;Small chance of the use of the Monero cryptocurrency to counter funding issues&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;b&gt;What could the government do?&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;It isn&#39;t talked about enough but the UK basically said they are done with the authoritarian approach and from my friends in the UK, things are back to normal and have been for a long, long time. See &lt;a href=&quot;https://www.youtube.com/watch?v=9KQKhcLRO3o&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; for more. No vaccination passport, etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The Canadian government could follow suit. Unlikely, but possible.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;What is &quot;big picture&quot; next?&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Many are watching similar protests worldwide to see what comes of them. Do governments blink, or does authoritarian policy win? If the latter, that sets the stage for the much desired &quot;one world&quot; government, which more or less already exists.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Central banks move together. Government policy moves together, usually led by the US but recently Chinese style policy is making its way to world governments. For example, recently the President of the CCP more or less threatened further supply chain issues if the Federal reserve of the US raised interest rates. They are already cooperating for the most part and anyone who can move between the worlds with ease can control it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So if the protests can be quashed without losing moral authority, and maintaining power, that gives the elite the confirmation that they do indeed have very strong control over much of the world economy. And as said in a previous post, they are very much happy with the fact that they get along well together.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Pop quiz&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;The following is a chart of Canadian government spending as a percentage of GDP. Guess when Canada went off the gold standard.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEhOULNeUoNKGcdLFwxOfteJiCOjY-fBJfkjw7l-67nMK-fR0yXucxQuBTT6fyWzgKaFWk7SXoC9ontuZhganvJ-lt3JmVzb31IsF7JpEMyjmqbaz51WoWMUZZhqRw4MoXkZeZTXQeS7vfkkVkgiXxFmC6QLnVT7768yZfRAuYmPXlsvZh99ncBDeewZsA&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;433&quot; data-original-width=&quot;710&quot; height=&quot;244&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEhOULNeUoNKGcdLFwxOfteJiCOjY-fBJfkjw7l-67nMK-fR0yXucxQuBTT6fyWzgKaFWk7SXoC9ontuZhganvJ-lt3JmVzb31IsF7JpEMyjmqbaz51WoWMUZZhqRw4MoXkZeZTXQeS7vfkkVkgiXxFmC6QLnVT7768yZfRAuYmPXlsvZh99ncBDeewZsA=w400-h244&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/b&gt;&lt;div&gt;No, it wasn&#39;t 1970. Yep, it&#39;s the first bump.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Why? Because government needed to fund itself without constraints. It&#39;s hard to know what the outcome is for situations like this, but history is probably a better guide than intuition. So the thought experiment to perform is as simple as: &quot;What civilization am I aware of that has lasted for hundreds of years with a government that takes up more than 50% of GDP and where a primary component of GDP growth is housing?&quot;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The answer of course, is none. Maybe this time it&#39;s different.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;How to prepare?&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;There is a lot of money to be made between now and when it stops working.&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Not much us plebs can do. However, if you wish to become one of the self-styled global elite, I believe you just have to have the desire, be great at networking and have a modicum of independent or government derived wealth. Not ironically, I suspect independent wealth goes further for this.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;</description><link>http://uint32t.blogspot.com/2022/01/whats-next-and-apology.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEhOULNeUoNKGcdLFwxOfteJiCOjY-fBJfkjw7l-67nMK-fR0yXucxQuBTT6fyWzgKaFWk7SXoC9ontuZhganvJ-lt3JmVzb31IsF7JpEMyjmqbaz51WoWMUZZhqRw4MoXkZeZTXQeS7vfkkVkgiXxFmC6QLnVT7768yZfRAuYmPXlsvZh99ncBDeewZsA=s72-w400-h244-c" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-3973270804001623074</guid><pubDate>Wed, 26 Jan 2022 23:36:00 +0000</pubDate><atom:updated>2022-01-27T15:46:03.274-05:00</atom:updated><title>The future (is now)</title><description>&lt;p&gt;Quick post...&lt;/p&gt;&lt;p&gt;In a &lt;a href=&quot;https://uint32t.blogspot.com/2021/10/the-future.html&quot;&gt;previous post&lt;/a&gt;, I talked about how I thought there would be a greater lock down of society and people would object.&lt;/p&gt;&lt;p&gt;While I&#39;m not sure a greater lock down has occurred, I have noticed that media and self-styled elites are further creating a divide between you-know-who and you-know-who-not. Divide and conquer is a strategy as old as time. Unfortunately, most people are unsophisticated thinkers and fall victim to the game, handing the elite power on a platter. I&#39;m sure I have done the same many times.&lt;/p&gt;&lt;p&gt;In that post I said:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;There will be an attempt to wholly lock down society worse than what we&#39;ve had the past two years. It will fail. It will be messy. It will not work. People will refuse it. &lt;b&gt;People who matter to the smooth running of the economy&lt;/b&gt;, which is after all, anything anyone cares about these days.&lt;/p&gt;&lt;p&gt;The cultural elites driving this lock down will be caught off guard as they were caught off guard by he-who-shall-not-be-named. &lt;b&gt;As with anyone losing power, they will try to increase their grip&lt;/b&gt;. It will be bad.&lt;/p&gt;&lt;p&gt;But in the end, the people will refuse to participate and will develop the leverage needed to add the right checks and balances to a system that is sorely lacking them. &lt;b&gt;I doubt it will be violent.&lt;/b&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;We are at that point now where there is a mass trucker protest which they basically can&#39;t ignore. They tried, but it is too large now. The truckers matter to the smooth running of the economy. If there are going to be shortages and even worse inflation as a result of this strike, that is the people exercising their power against the government in a nonviolent manner. They can no longer blame a boogieman, even if state run news (lol) refuses to cover it.&lt;/p&gt;&lt;p&gt;The only way governments can respond are as follows:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Accede/respond to demands and begin good faith negotiations&lt;/li&gt;&lt;li&gt;Ignore the demands. Usually leads to government being toppled.&lt;/li&gt;&lt;li&gt;Demand an end to the protest and respond with violence if the protest does not end&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Surely there are other possible responses. What does history say governments do when their people protest in a massive organized fashion?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is a long history of (3) in all professed &quot;developed&quot; countries. One might even say the US government response to Jan 6 falls under (3).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So the Canadian government response will be interesting. Will the enforcers support the leaders if they require violence?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I&#39;m not so sure.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In any case, it will be interesting.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Other countries have already been doing mass protests for a long time. France, in particular. But mass protests in France are like brunch on Sundays, it&#39;s not guaranteed, but it&#39;ll happen.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Whether you want to believe it or not, the past two years have been basically a gift to the self-congratulating elites of the world. I wish I had the clip handy, but there is a woman at the WEF saying something to the effect of:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;The good news is: we, the elite, get along better than ever! The bad news is: no one in our countries trusts us.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;She actually did call herself elite. I wish I was kidding.This is how they see themselves. How do they see us?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Joe Rogan covering the protest:&amp;nbsp;&lt;a href=&quot;https://twitter.com/iwillchaseu/status/1486456133015511047&quot;&gt;https://twitter.com/iwillchaseu/status/1486456133015511047&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Update: Justin Trudeau has chosen to leave Ottawa which is a version of (2). Hmm...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;</description><link>http://uint32t.blogspot.com/2022/01/the-future-is-now.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-3264498018425884546</guid><pubDate>Tue, 26 Oct 2021 23:52:00 +0000</pubDate><atom:updated>2021-10-26T19:52:45.080-04:00</atom:updated><title>The future</title><description>&lt;p&gt;&lt;a href=&quot;https://uint32t.blogspot.com/2011/05/learning-about-bitcoin-or-why-i-never.html&quot; target=&quot;_blank&quot;&gt;This blog&lt;/a&gt; shows that I am often early on trends. It took me a long time to realize this was the case. I&#39;m not necessarily wrong, just early. I also don&#39;t really prepare well for trends that aren&#39;t potentially disastrous. For example, Bitcoin. Had I known how prices are determined (hint: what someone is willing to pay), I would have made different decisions.&lt;/p&gt;&lt;p&gt;Other trends I saw coming:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Golden handcuffs: The first time I saw someone get fired I said that I will never put myself in a position where I rely on a job. As a result, I have built multiple streams of income which have lasted for decades at this point and every year I try to add one more, usually unsuccessfully.&lt;/li&gt;&lt;li&gt;Remote work: Somewhat tied to the first, I have insisted on remote work (for the most part) for over 10 years. This is mildly tied to &lt;a href=&quot;https://uint32t.blogspot.com/2021/08/if-software-engineering-is-in-demand.html&quot;&gt;the logic here&lt;/a&gt;&amp;nbsp;(tl;dr: people hire other people like themselves, I am not like other people so I try to avoid being in that position.) My two favorite positions I left because of lack of remote work instituted remote work within a year after my departure. Only a year early although the two events were nearly a decade apart!&lt;/li&gt;&lt;li&gt;A segregation between the elites and the rest of society. In the 2000s, I noticed that the culture had shifted to propagandizing families against each other. Cultural elites know that at the end, legacy is what matters. I remarked to a friend that marriage will be a consideration only for cultural elites in the near future. A few years later, I came across &lt;a href=&quot;https://www.amazon.com/Coming-Apart-State-America-1960-2010/dp/030745343X/&quot; target=&quot;_blank&quot;&gt;a really great book&lt;/a&gt; which confirmed my suspicions &lt;a href=&quot;https://www.econlib.org/archives/2012/02/my_two_favorite.html&quot;&gt;in data&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;So what am I seeing today? A societal rip that is being exaggerated by an increasingly irrelevant media desperate to retain its control over the narrative. For a simple example, consider the distribution of feelings of those you know regarding vaccination status. Extreme on both sides, and being promoted by all media. Meanwhile, talk to someone who is off grid, they really don&#39;t care. Yes they&#39;ll wear a mask when they go into town, and no they won&#39;t otherwise.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To maintain control and push forward The True Narrative, the Internet will necessarily need to be locked down. We already saw this with the banning of a US president from social media. In my opinion, this should have shocked everyone, regardless of their political affiliation and should have been vehemently opposed by everyone. However, due to the aforementioned rip, it was quite easy to find out where one stood politically based on how they perceived that event. After all, I don&#39;t like the guy so it&#39;s better if he doesn&#39;t get to speak. This has since spilled over to censoring of all sorts of factual information on platforms like YouTube.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I don&#39;t know if I see this getting better without a major loss.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So what is the trend that I am possibly early (or maybe even late) on today?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There will be an attempt to wholly lock down society worse than what we&#39;ve had the past two years. It will fail. It will be messy. It will not work. People will refuse it. People who matter to the smooth running of the economy, which is after all, anything anyone cares about these days.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The cultural elites driving this lock down will be caught off guard as they were caught off guard by he-who-shall-not-be-named. As with anyone losing power, they will try to increase their grip. It will be bad.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But in the end, the people will refuse to participate and will develop the leverage needed to add the right checks and balances to a system that is sorely lacking them. I doubt it will be violent.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I want to be wrong, but I also don&#39;t want to be wrong because I want that new component of checks and balances.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Am I really doing anything to prepare? No, not really. I don&#39;t expect it to be disastrous. Plus, I&#39;m probably already late.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;</description><link>http://uint32t.blogspot.com/2021/10/the-future.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-1313695741278339731</guid><pubDate>Mon, 30 Aug 2021 21:27:00 +0000</pubDate><atom:updated>2021-08-30T17:30:21.909-04:00</atom:updated><title>If software engineering is in demand, why is it so hard to get a job?</title><description>&lt;p&gt;Title taken from here:&amp;nbsp;&lt;a href=&quot;https://news.ycombinator.com/item?id=28355658&quot; target=&quot;_blank&quot;&gt;https://news.ycombinator.com/item?id=28355658&lt;/a&gt;&amp;nbsp;where there is lots of speculation about why job searching in software is so Kafka-esque.&lt;/p&gt;&lt;p&gt;Without fail, every job I have ever taken is one where I was not super qualified but the other people in the job were like me in some way. Either they were independently minded, immigrants, liked Lisp for whatever stupid reason or wanted to do great things with people who wanted to do great things.&lt;/p&gt;&lt;p&gt;So looking for a job, in software, is about finding people like you. You can be perfectly qualified for the position, but if it&#39;s a company full of Chadbros, they want other Chadbros, if it&#39;s a company of bronies (yes, I&#39;ve seen one, it was hilarious, and I loved it), they want people who don&#39;t challenge their bronyhood.&lt;/p&gt;&lt;p&gt;Let&#39;s take a look at the &quot;About us&quot; screenshots from some recently &quot;Who&#39;s hiring&quot; from Hacker News. Note that I&#39;m absolutely not picking on these people, just pointing out some observations.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://lh3.googleusercontent.com/-ySbwZngt-Lg/YS1FNIA8whI/AAAAAAAAWjg/RkvCXa5VzV8HvWT1eWFB6WrJDIIA5kdvQCLcBGAsYHQ/image.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;740&quot; data-original-width=&quot;1100&quot; height=&quot;269&quot; src=&quot;https://lh3.googleusercontent.com/-ySbwZngt-Lg/YS1FNIA8whI/AAAAAAAAWjg/RkvCXa5VzV8HvWT1eWFB6WrJDIIA5kdvQCLcBGAsYHQ/w400-h269/image.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;Commonality here could be: peppy personality&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://lh3.googleusercontent.com/-M5apfIhw9Xk/YS1F33GiO5I/AAAAAAAAWjo/jjhfLbwYCrEe-_hX0p3dMkzcee8QMp6XgCLcBGAsYHQ/image.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;622&quot; data-original-width=&quot;969&quot; height=&quot;293&quot; src=&quot;https://lh3.googleusercontent.com/-M5apfIhw9Xk/YS1F33GiO5I/AAAAAAAAWjo/jjhfLbwYCrEe-_hX0p3dMkzcee8QMp6XgCLcBGAsYHQ/w457-h293/image.png&quot; width=&quot;457&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;Commonality here could be: fantastic hair&lt;/div&gt;&lt;br /&gt;You can keep going and they will all pretty much appear to share some commonality.&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;For comparison, here is a picnic:&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://lh3.googleusercontent.com/-egIDPZm56R4/YS1KjajuR9I/AAAAAAAAWj4/ic8yDkBzGrIhJjcUVyuIleM0EXAmydpHgCLcBGAsYHQ/image.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;385&quot; data-original-width=&quot;640&quot; height=&quot;193&quot; src=&quot;https://lh3.googleusercontent.com/-egIDPZm56R4/YS1KjajuR9I/AAAAAAAAWj4/ic8yDkBzGrIhJjcUVyuIleM0EXAmydpHgCLcBGAsYHQ/image.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Commonality here could be: people who like to have fun&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Notice the picnic have a different &quot;kind of people&quot;, even though presumably they all love to see their kids have fun.&lt;/p&gt;&lt;p&gt;So why do tech companies end up looking like the above?&lt;/p&gt;&lt;p&gt;Very simply: they know &quot;their&quot; kind of people and know how to get along with &quot;their&quot; kind of people. Whether this is brony, chad, young, old, culture 1, culture 2, etc, that is what _all_ interviews are about. The actual questions asked in the interview &lt;b&gt;do not matter &lt;/b&gt;beyond basic some competence.&lt;/p&gt;&lt;p&gt;This is why interviewing has become a job in itself. Some people think it&#39;s perfectly normal to have 5 rounds of interviews but what is really happening here is: &quot;would you like to spend time with this person&quot;.&lt;/p&gt;&lt;p&gt;This is also why networking is the best way to get a job if you are looking. You are already &quot;their&quot; people.&lt;/p&gt;&lt;p&gt;If you go for an interview, your job is pretty much to find out if you are compatible. It&#39;s a date. You&#39;ll know you&#39;re in if they help you eagerly with whatever fizzbuzz question they give you.&lt;/p&gt;&lt;p&gt;Yes I know people will say &quot;how dare you, our interview process is supremely objective&quot;, but to provide my own anecdata, I&#39;ve never gotten a job on technical merits, and I&#39;ve had more than one offer over the years from big tech. Why I didn&#39;t take them is another story.&lt;/p&gt;&lt;p&gt;Many years ago, I was interviewing (blind) with one of those &quot;interview with us and you get a job at FAANG&quot; shops. I nailed everything technically, to the point where they said I was the best they had seen (could have been stroking my ego, who knows). I go onsite, and it could have been a bad day, they didn&#39;t like my hair, but the chemistry that was there remotely, on the days before zoom, disappeared and even though I nailed their onsite technical interviews as well - implementing Tetris I think - somehow, there was a complete cold distance. Shit, I even did it in Clojure, a language I hadn&#39;t learned before &lt;i&gt;that day&lt;/i&gt;. So it wasn&#39;t technical at all.&lt;/p&gt;&lt;p&gt;It took me a while to understand what actually happened. They were not my people and I was not theirs. In fairness, I am not most people&#39;s people. It is what it is.&lt;/p&gt;&lt;p&gt;So look for people who are like you along some axis, or try to find some commonality beyond just answering the questions if you really want a shot at that job.&lt;/p&gt;&lt;p&gt;I realize that adds yet another dimension but in my opinion, it&#39;s the most important one.&lt;/p&gt;&lt;p&gt;My honest advice if you are looking for a job is: enjoy the tech interview process. The questions that everyone complains about can be fun and an opportunity to learn, whether you get a job is not even relevant. It&#39;s basically luck of the draw in the end. And focus on first impressions, those matter quite a bit.&lt;/p&gt;</description><link>http://uint32t.blogspot.com/2021/08/if-software-engineering-is-in-demand.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/-ySbwZngt-Lg/YS1FNIA8whI/AAAAAAAAWjg/RkvCXa5VzV8HvWT1eWFB6WrJDIIA5kdvQCLcBGAsYHQ/s72-w400-h269-c/image.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-8231002794480812865</guid><pubDate>Fri, 30 Jul 2021 22:44:00 +0000</pubDate><atom:updated>2021-07-30T18:44:29.477-04:00</atom:updated><title>Y&#39;s vs non-Y&#39;s (the parable of the software consultant)</title><description>&lt;p&gt;Client: How much do you think it will cost to get the project done?&lt;/p&gt;&lt;p&gt;Consultant: Probably $X in P periods of time&lt;/p&gt;&lt;p&gt;Client: $X is too high, I can get 4 Ys for $X.&lt;/p&gt;&lt;p&gt;Consultant: OK, go for it.&lt;/p&gt;&lt;p&gt;... 2 x P periods of time pass ...&lt;/p&gt;&lt;p&gt;Client: Hey... The Ys didn&#39;t work out and the project is almost a writeoff. Can you come onto the project?&lt;/p&gt;&lt;p&gt;Consultant: Since I need to undo the damage first, it will cost $(X+Z)&lt;/p&gt;&lt;p&gt;Client: OK.&lt;/p&gt;&lt;p&gt;(Based on many true stories, names have been changed to protect the innocent.)&lt;/p&gt;&lt;p&gt;In my experience, the reason this happens is because software is eating the world, but deep knowledge of how software is built is still locked up in the old guard, some people coming out of high-tech FAANG-like companies, as well as some independent developers.&lt;/p&gt;&lt;p&gt;The rest of the industry is focused on leftpad-gate, and arguing over Javascript front-end frameworks etc while the art of developing software is honed by very few.&lt;/p&gt;&lt;p&gt;The flip side of the coin is the Y&#39;s can actually do a great job when it comes to software that follows a beaten path. For example, a standard web app with a React front-end. This is why everyone wants to know &quot;your stack&quot;. Y&#39;s beat out non-Y&#39;s 99/100 times here in my experience.&lt;/p&gt;&lt;p&gt;Many conflate the proficiency of Y&#39;s with their home stack with software development expertise. I have found that this is usually not the case. They are SDK developers (which is perfectly fine, quite lucrative and very useful, please don&#39;t get me wrong.) If you take them out of their stack, they are lost.&lt;/p&gt;&lt;p&gt;The proficiency with Y projects (which vastly outnumber non-Y projects) trick you into thinking that you can use a Y for a non-Y project. You cannot.&lt;/p&gt;&lt;p&gt;When you get beyond Y projects, building software to support what is coming down the line is near impossible for Y&#39;s since there is no way for them to create something that doesn&#39;t exist. Y&#39;s can use a stack, but they can&#39;t create a stack.&lt;/p&gt;&lt;p&gt;For non-Y&#39;s, they are usually not interested in standard CRUD apps with React front-ends, so they are willing to wait for interesting projects to come to them.&lt;/p&gt;&lt;p&gt;I think the Y&#39;s and non-Y&#39;s are complementary and there is no need to pick a better side.&lt;/p&gt;&lt;p&gt;I know non-Y&#39;s who wish they could be Y&#39;s and I know Y&#39;s who yearn to be non-Y but do not get the opportunity. Maybe their paths are chosen years in advance by some fluke of life and the results compounded without their active consent.&lt;/p&gt;</description><link>http://uint32t.blogspot.com/2021/07/ys-vs-non-ys-parable-of-software.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-3129197336211631445</guid><pubDate>Wed, 03 Aug 2016 15:10:00 +0000</pubDate><atom:updated>2016-08-03T11:10:47.968-04:00</atom:updated><title>Achieving goals using TeamCity</title><description>As a small company of 1 + sub contractors, I have very little room or patience for doing things I don&#39;t need to do. The concept of being an architecture astronaut is not new to me, as I have both designed and coded myself into a corner in the past so I am acutely aware of the &lt;a href=&quot;https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it&quot; target=&quot;_blank&quot;&gt;YAGNI&lt;/a&gt; philosophy.&lt;br /&gt;&lt;br /&gt;A very important class of tasks fall into the bucket of &quot;things I need to do, but manually.&quot; This might include:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Updating a sales database&lt;/li&gt;&lt;li&gt;Generating development metrics to guage project health&lt;/li&gt;&lt;li&gt;Monitoring license count/usage, bumping the count if needed or &quot;upselling&quot; the end user&lt;/li&gt;&lt;li&gt;Announcing releases&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;These are all real tasks that I need to do every day/week/month. All of these are manual. Slowly, but surely, I am replacing them with automated scripts. That&#39;s not really too interesting.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The interesting part is that I&#39;m using TeamCity to create the workflows to support all of these. At a quick glance:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://3.bp.blogspot.com/-vRchGxLAFio/V6H1l69Q0CI/AAAAAAAAB8E/NOvoULvQQfwjx29Po8SmhIXa5RYrZFGrwCK4B/s1600/teamcity.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;169&quot; src=&quot;https://3.bp.blogspot.com/-vRchGxLAFio/V6H1l69Q0CI/AAAAAAAAB8E/NOvoULvQQfwjx29Po8SmhIXa5RYrZFGrwCK4B/s400/teamcity.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;TeamCity: not just for building software&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Some projects/configurations are hidden, but this gives you the general idea. I not only use TeamCity for building and testing the software I write, but I use it to export sales, update mailing lists, generating development metrics and even automatically creating blog posts/emails announcing new releases.&lt;/div&gt;&lt;h2&gt;Why would I do this?&lt;/h2&gt;&lt;div&gt;Basically, I am buying myself time. By putting in a little bit of work ahead of time, I save myself man-months of work in the future.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What this really allows me to do, and is the ultimate goal, is focus on talking with customers. To create conversations with customers, you have to give them something they can talk about in the first place.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So every thought process is geared towards getting the customer communicating their pleasure, or displeasure with software they use.&lt;/div&gt;&lt;h2&gt;Why is TeamCity the right tool to do this?&lt;/h2&gt;&lt;div&gt;Well, for me it works because:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;I already use it and know it&lt;/li&gt;&lt;li&gt;TeamCity has a very good concept of inputs and outputs: build artifacts. This is primarily what makes my non-build workflows possible&lt;/li&gt;&lt;li&gt;My design process is agnostic of the tools/techniques I use, and so I can fit in whatever tool works best.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;But before I choose the tool, I have a process for choosing an implementation. I&#39;ve outlined the process below. I cannot take credit for this process as it was taught to me and I&#39;ve honed it in the last little while.&lt;/div&gt;&lt;h2&gt;The process&lt;/h2&gt;&lt;h3&gt;1. Choose a goal&lt;/h3&gt;&lt;div&gt;Before I choose a tool to do the job, I look at the goal. While the high-level goal is obviously customer satisfaction (80% of people choose the &quot;It&#39;s just perfect - thanks mom&quot; option in recent surveys so I&#39;m hitting that target pretty well), there are sub-goals that will help me get there. For an example, let&#39;s pick the &lt;b&gt;&quot;Notify customers of an update&quot;&lt;/b&gt; goal.&lt;/div&gt;&lt;h3&gt;2. Create a design&lt;/h3&gt;&lt;div&gt;Next, I create a design to implement the goal. For example, here is the design I used to determine what happens when I commit a change. It&#39;s pretty standard though this evolved over the period of a few months. The purpose of creating this design is to let me go back to it and modify it when things change. Nothing is in my head, it&#39;s all here. This is a huge difference from only a couple of years ago where I would keep everything in my head.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://1.bp.blogspot.com/-gsiBWfqQTRQ/V6H6kshr3NI/AAAAAAAAB8U/q1gBmMtN4dg4XW4jvlVdxpExiWtxc89WwCK4B/s1600/run_build.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;211&quot; src=&quot;https://1.bp.blogspot.com/-gsiBWfqQTRQ/V6H6kshr3NI/AAAAAAAAB8U/q1gBmMtN4dg4XW4jvlVdxpExiWtxc89WwCK4B/s400/run_build.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h3&gt;3. Mark up the design where tools implement the required functionality&lt;/h3&gt;&lt;div&gt;The next step is usually to print it out and circle places where I think tools will do the job I need. I simulated this with SnagIt as I only JUST recycled my actual notes for this particular diagram. Murphy&#39;s Law strikes again.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://2.bp.blogspot.com/-PRRqM_tJUcA/V6H_1WKBd0I/AAAAAAAAB8s/OJPFI3ZkdtoukJPGvCzFs-Kb3W5l21UVgCK4B/s1600/run_build_markup.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;169&quot; src=&quot;https://2.bp.blogspot.com/-PRRqM_tJUcA/V6H_1WKBd0I/AAAAAAAAB8s/OJPFI3ZkdtoukJPGvCzFs-Kb3W5l21UVgCK4B/s320/run_build_markup.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;Why do this? Very simple: who wants to write a ton of code that isn&#39;t necessary? Outsource as much as possible to free (as in beer) software, commercial, whatever is needed to get you to your goal.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;By doing things in this way, and keeping an eye on choosing things that let me do as little work as possible, I end up with a very lean design and most importantly, a lean implementation.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;You can see the big arrow is the key piece here allowing me to outsource nearly 100% of the &quot;notify users of an update&quot; functionality. By linking in certain libraries on certain platforms and generating a very specific format of an update manifest, I can support updates on Windows, OSX and Linux.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;In particular, Linux was super simple. Can you match the code below to the design above? It should be pretty straightforward.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;cd $WLA_ROOT/build&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;export GNUPGHOME=$WLA_ROOT/dev/ci/keys/gpg&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;$WLA_ROOT/dev/scripts/run_gpg_command dpkg-sig -g &quot; --yes&quot; \&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;--sign builder *.deb &amp;amp;&amp;amp; \&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; rm -rf repo &amp;amp;&amp;amp; \&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; mkdir repo &amp;amp;&amp;amp; \&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; cp *.deb repo &amp;amp;&amp;amp; \&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; cd repo &amp;amp;&amp;amp; \&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dpkg-scanpackages . /dev/null &amp;gt; Packages) &amp;amp;&amp;amp; \&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (bzip2 -kf Packages) &amp;amp;&amp;amp; \&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (apt-ftparchive release . &amp;gt; Release) &amp;amp;&amp;amp; \&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ($WLA_ROOT/dev/scripts/run_gpg_command gpg --yes -abs -o Release.gpg Release) &amp;amp;&amp;amp; \&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (gpg --export --armour &amp;gt; archive.key)&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;clear: both; text-align: left;&quot;&gt;So... Why did you choose TeamCity when an actual workflow tool would do just fine?&lt;/h2&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://1.bp.blogspot.com/-Pvyt4iP2GwE/V6ID8ulmu5I/AAAAAAAAB9A/uSmu7rG2hawMhzhKQYpjewMEFM0yZoPiQCK4B/s1600/run_build_artifacts.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;211&quot; src=&quot;https://1.bp.blogspot.com/-Pvyt4iP2GwE/V6ID8ulmu5I/AAAAAAAAB9A/uSmu7rG2hawMhzhKQYpjewMEFM0yZoPiQCK4B/s400/run_build_artifacts.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;Here is a version of the markup that makes it obvious where TeamCity can help: the package and manifest are treated as artifacts. The screenshot below, directly from TeamCity shows how treating the inputs and outputs as build artifacts allows the use of TeamCity as a tool for the rest of the process (after building and testing is complete):&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://4.bp.blogspot.com/-JJAll0k3UMw/V6IFjTnu_HI/AAAAAAAAB9M/Lslu4ZOnJsw3sloOlc8hIGoLkcK5Ml0OQCK4B/s1600/teamcity_artifacts_inputs.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;171&quot; src=&quot;https://4.bp.blogspot.com/-JJAll0k3UMw/V6IFjTnu_HI/AAAAAAAAB9M/Lslu4ZOnJsw3sloOlc8hIGoLkcK5Ml0OQCK4B/s400/teamcity_artifacts_inputs.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Inputs for the &quot;notify users of an update&quot; box matching nearly 1:1 from design above. Linux has &quot;15&quot; because the &quot;manifest&quot; is a directory with a bunch of files in it so apt/yum &amp;nbsp;can do their job. Technically, I could zip that directory up and make it a single artifact.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;h2 style=&quot;clear: both; text-align: left;&quot;&gt;What else do I get for free?&lt;/h2&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;This is my favourite part of doing things like above: you get a ton for free. By integrating the everything into TeamCity, I get:&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;Build history&lt;/li&gt;&lt;li&gt;Artifact history&lt;/li&gt;&lt;li&gt;Configuration management&lt;/li&gt;&lt;li&gt;Project metrics (I specifically track LOC to make sure I&#39;m not going too crazy):&lt;/li&gt;&lt;/ol&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://3.bp.blogspot.com/-CCVsCSlNxGw/V6IH_zeb1vI/AAAAAAAAB9Y/oCpHEvuESYsFYuY43BVxH2pIm3AekowQgCK4B/s1600/code_metrics.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;75&quot; src=&quot;https://3.bp.blogspot.com/-CCVsCSlNxGw/V6IH_zeb1vI/AAAAAAAAB9Y/oCpHEvuESYsFYuY43BVxH2pIm3AekowQgCK4B/s400/code_metrics.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;clear: both; text-align: left;&quot;&gt;Conclusion&lt;/h2&gt;&lt;div&gt;I just wanted to record my thought process for posterity. Enjoy!&lt;/div&gt;&lt;br /&gt;</description><link>http://uint32t.blogspot.com/2016/08/achieving-goals-using-teamcity.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://3.bp.blogspot.com/-vRchGxLAFio/V6H1l69Q0CI/AAAAAAAAB8E/NOvoULvQQfwjx29Po8SmhIXa5RYrZFGrwCK4B/s72-c/teamcity.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-197997439708530153</guid><pubDate>Thu, 02 Jun 2016 03:35:00 +0000</pubDate><atom:updated>2021-10-26T23:36:18.317-04:00</atom:updated><title>There is a very simple reason why the DAO was easily hacked</title><description>&lt;a href=&quot;http://blog.erratasec.com/2016/06/etheriumdao-hack-similfied.html&quot; target=&quot;_blank&quot;&gt;Background here&lt;/a&gt;.&amp;nbsp;TL;DR: a smart contract &quot;worth&quot; about $150 million USD was &quot;hacked&quot; and had $45 million USD moved to accounts controlled by the hacker.&lt;br /&gt;&lt;br /&gt;The &quot;DAO&quot; is an instance of &quot;code as legal contract&quot; run using a Bitcoin-like technology called Ethereum. The programming language for Ethereum is imperative for reasons that escape me, but are probably legit - likely simplicity and user friendliness.&lt;br /&gt;&lt;br /&gt;There is a very simple reason why the DAO was easily hacked: the code is shit.&lt;br /&gt;&lt;br /&gt;The &lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;a href=&quot;https://raw.githubusercontent.com/slockit/DAO/develop/DAO.sol&quot; target=&quot;_blank&quot;&gt;contract&lt;/a&gt;&lt;/span&gt;&amp;nbsp;(it doesn&#39;t matter if this is the deployed version or not) is about 300 lines long. It has the equivalent of 15 constants, 15 public fields, 2 nested classes and 25 functions.&lt;br /&gt;&lt;br /&gt;25 functions all jumbled into one contract.&lt;br /&gt;&lt;br /&gt;Would you let this pass code review? Most people would not. The organization of this contract was such that the quality of implementation was obvious from a first glance. The fact that this &quot;hack&quot; exists is not surprising. 25 operations on a type indicate that there is too much flexibility, and likely very little thought went into creating the correct abstractions. I say this from humbled experience.&lt;br /&gt;&lt;br /&gt;As long as the Ethereum miners don&#39;t bail out the DAO, the concept of the Ethereum blockchain is fine. The DAO &lt;b&gt;should &lt;/b&gt;fail to teach them a lesson. Bitcoin went through its own growing pains with all the exchange hacks forcing beefing up security.&lt;br /&gt;&lt;br /&gt;There is an ongoing &lt;a href=&quot;https://news.ycombinator.com/item?id=11928092&quot; target=&quot;_blank&quot;&gt;discussion on Hacker News&lt;/a&gt; about the code behind the contract.&lt;br /&gt;&lt;br /&gt;All that being said, this incident should not turn people off Ethereum so long as the miners don&#39;t bail out the DAO. The technology is interesting, and this is the equivalent of the &lt;a href=&quot;https://ima.umn.edu/~arnold/disasters/ariane.html&quot; target=&quot;_blank&quot;&gt;Araine 5 explosion&lt;/a&gt; for Ethereum. A learning experience.</description><link>http://uint32t.blogspot.com/2016/06/there-is-very-simple-reason-why-dao-was.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-4094036222645757566</guid><pubDate>Sat, 06 Dec 2014 15:03:00 +0000</pubDate><atom:updated>2014-12-06T12:43:22.870-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">git</category><category domain="http://www.blogger.com/atom/ns#">mercurial</category><title>Why I moved to Git from Mercurial</title><description>There are stories everywhere about how Git is eating everyone&#39;s lunch. For a long time, I happily used Mercurial primarily because I needed a cross-platform DVCS that had a sane command-line interface. I don&#39;t think there is much disagreement that the first few iterations of git were not very portable nor was the command-line very friendly. Mercurial has been in daily use by me very nearly since it came out and I don&#39;t have any complaints. It&#39;s that good. So why move?&lt;br /&gt;&lt;br /&gt;One word: &lt;a href=&quot;https://magit.github.io/&quot;&gt;Magit&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The only Emacs packages for Mercurial I tried (vc.el and &lt;a href=&quot;https://github.com/ananthakumaran/monky&quot;&gt;Monky&lt;/a&gt;) were very basic. Monky, an imitation of Magit, was a very superficial approach and vc.el still hasn&#39;t moved very far out of the days of centralized version control, though it has somewhat. Additionally, Magit has a killer feature that rightfully matches Git&#39;s killer feature: editing the index.&lt;br /&gt;&lt;div class=&quot;outline-2&quot; id=&quot;outline-container-sec-1&quot;&gt;&lt;h2 id=&quot;sec-1&quot;&gt;ADHD Coding and the Index&lt;/h2&gt;&lt;div class=&quot;outline-text-2&quot; id=&quot;text-1&quot;&gt;Sometimes, due to what I assume is late-blooming ADHD, I go on development tangents where I fix bugs and/or add little features here and there. When it comes time to commit, I have many changes intermixed with one another and committing them all at the same time is a terrible idea for a clean, readable history.&lt;br /&gt;&lt;br /&gt;Git&#39;s source editing process works like this: edit -&amp;gt; stage -&amp;gt; commit. Until you stage something, it cannot not be committed. Take a look at the &lt;a href=&quot;http://git-scm.com/book/en/v2/Getting-Started-Git-Basics&quot;&gt;Git book&lt;/a&gt; for more information.&lt;br /&gt;&lt;br /&gt;What Magit allows you to do superbly (obviously through Git), is within each file, &quot;stage&quot; the only the changes you want. So if you have 3 blocks of changes within a file, you can choose to only stage the one change without reverting the other 2. Now you can commit related changes together even if you worked on multiple things at the same time.&lt;br /&gt;&lt;br /&gt;So when using the ADHD development methodology described above, staging diff hunks is ridiculously helpful and Magit makes it easy to do the right thing even for simpletons: s for stage, u for unstage. I never did try very hard to figure out how to do it with Mercurial but I think I remember hearing the word &quot;plugin&quot; or &quot;queues&quot; before I zoned out.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;outline-2&quot; id=&quot;outline-container-sec-2&quot;&gt;&lt;h2 id=&quot;sec-2&quot;&gt;Projects&lt;/h2&gt;&lt;div class=&quot;outline-text-2&quot; id=&quot;text-2&quot;&gt;I&#39;ve moved most of my private repositories, including my &lt;a href=&quot;http://worklogassistant.com/&quot;&gt;JIRA time&amp;nbsp;tracker&lt;/a&gt; over to Git as well as my &lt;a href=&quot;https://bitbucket.org/cheez/dicpp&quot;&gt;dependency injection library for&amp;nbsp;C++&lt;/a&gt;. Switching to Git for continuous builds was easy as pie. The only real change I had to make was the bit of the build that grabbed the HEAD revision:&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;org-src-container&quot;&gt;&lt;pre class=&quot;src src-diff&quot;&gt;&lt;span style=&quot;color: #8b8682;&quot;&gt;diff --git a/ConfigureWorklogAssistant.cmake b/ConfigureWorklogAssistant.cmake&lt;/span&gt;&lt;span style=&quot;color: #8b8682;&quot;&gt;index 988f6c4..1fb5d36 100644&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #737373;&quot;&gt;--- &lt;/span&gt;&lt;span style=&quot;background-color: #999999;&quot;&gt;a/ConfigureWorklogAssistant.cmake&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #737373;&quot;&gt;+++ &lt;/span&gt;&lt;span style=&quot;background-color: #999999;&quot;&gt;b/ConfigureWorklogAssistant.cmake&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #737373;&quot;&gt;@@ -32,8 +32,9 @@&lt;/span&gt;&lt;span style=&quot;background-color: #737373;&quot;&gt; macro(define_kimi_product OutputFileVar ProductGUID CompanyName&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #8b8682;&quot;&gt;   set(KIMI_PRODUCT_SOURCE_REVISION)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #8b8682;&quot;&gt;   execute_process(&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #8b3a3a; color: white;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;background-color: #553333;&quot;&gt;    COMMAND hg head tip --template &quot;{rev}&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: darkolivegreen; color: white;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color: #335533;&quot;&gt;    COMMAND git log -n 1 --format=%h&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #8b8682;&quot;&gt;     OUTPUT_VARIABLE KIMI_PRODUCT_SOURCE_REVISION&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: darkolivegreen; color: white;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;background-color: #335533;&quot;&gt;    OUTPUT_STRIP_TRAILING_WHITESPACE&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #8b8682;&quot;&gt;     )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #8b8682;&quot;&gt;   configure_file(&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;outline-2&quot; id=&quot;outline-container-sec-3&quot;&gt;&lt;h2 id=&quot;sec-3&quot;&gt;The future&lt;/h2&gt;&lt;div class=&quot;outline-text-2&quot; id=&quot;text-3&quot;&gt;I am pretty much set with Git for now. The fact that it only took a few hours is probably a testament to how similar the two are. However, if Mercurial was to develop an interface as good as Magit, including supporting some form of staging in a big way, I think I would consider switching back. A DVCS written in Python is too delicious to ignore.&lt;/div&gt;&lt;/div&gt;</description><link>http://uint32t.blogspot.com/2014/12/why-i-moved-to-git-from-mercurial.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-5120544847090971432</guid><pubDate>Thu, 30 Oct 2014 13:25:00 +0000</pubDate><atom:updated>2014-10-30T12:30:25.584-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><title>A walk through a cool code generation trick from Clang</title><description>[edit: fixed css]&lt;br /&gt;&lt;br /&gt;If you don&#39;t know, &lt;a href=&quot;http://clang.llvm.org/&quot;&gt;Clang&lt;/a&gt; is an open source C, C++, Objective-C and Objective-C++ front-end for the LLVM compiler. Clang/LLVM contributors are probably some of the brightest software engineers you&#39;ll come across so there is always something to learn. Take a look at &lt;a href=&quot;http://llvmweekly.org/&quot;&gt;LLVM&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;http://llvmweekly.org/&quot;&gt;weekly&lt;/a&gt; to see the kinds of things people are working on. Just in the last week:&lt;br /&gt;&lt;ul class=&quot;org-ul&quot;&gt;&lt;li&gt;Improved MSVC/Golang/GCC support/compatibility&lt;/li&gt;&lt;li&gt;New intrinsics for the LLVM IR&lt;/li&gt;&lt;li&gt;A disassembler for the Hexagon backend&lt;/li&gt;&lt;/ul&gt;If you want to dig into the architecture of Clang/LLVM, you should read the &lt;a href=&quot;http://www.aosabook.org/en/llvm.html&quot;&gt;LLVM chapter&lt;/a&gt; from &quot;Architecture of Open Source Applications&quot;. In fact, both volumes of the book should be mandatory reading for anyone interested in software design and architecture.&lt;br /&gt;&lt;div class=&quot;outline-2&quot; id=&quot;outline-container-sec-1&quot;&gt;&lt;h2 id=&quot;sec-1&quot;&gt;The Clang Philosophy&lt;/h2&gt;&lt;div class=&quot;outline-text-2&quot; id=&quot;text-1&quot;&gt;&lt;div class=&quot;figure&quot;&gt;&lt;img alt=&quot;5H126L1.png&quot; src=&quot;https://i.imgur.com/5H126L1.png&quot; /&gt;&lt;br /&gt;&lt;span class=&quot;figure-number&quot;&gt;Figure 1:&lt;/span&gt; The Clang Philosophy, summed up by Xzibit&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;When building Clang itself, you are actually using 3 code generators:&lt;br /&gt;&lt;ul class=&quot;org-ul&quot;&gt;&lt;li&gt;The C++ compiler you are using to compile Clang&lt;/li&gt;&lt;li&gt;The C++ preprocessor&lt;/li&gt;&lt;li&gt;A DSL-to-C++ code generator called &lt;a href=&quot;http://llvm.org/releases/3.4/docs/TableGenFundamentals.html&quot;&gt;&lt;code&gt;tblgen&lt;/code&gt;&lt;/a&gt; - yes, there is&lt;br /&gt;literally a custom compiler used to build clang!&lt;/li&gt;&lt;/ul&gt;&lt;code&gt;tblgen&lt;/code&gt; is run during the build process to generate (usually) C++ code. Although I&#39;m not aware of it generating anything else, it could conceivably be used to do so. The purpose of the program is to help the developers maintain lists of domain-specific information. For example: allowable attributes on a function or types of nodes in the AST.&lt;br /&gt;&lt;br /&gt;Here is the example we&#39;re going to look at: &lt;a href=&quot;https://github.com/llvm-mirror/clang/blob/release_33/include/clang/Basic/Attr.td#L963&quot;&gt;&lt;code&gt;Attr.td&lt;/code&gt;&lt;/a&gt;. In particular, we&#39;ll follow the lines below into the final C++:&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;org-src-container&quot;&gt;&lt;pre class=&quot;src src-c++&quot;&gt;&lt;span style=&quot;color: deepskyblue;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #98f5ff;&quot;&gt;MSInheritanceAttr&lt;/span&gt; : &lt;span style=&quot;color: #98f5ff;&quot;&gt;InheritableAttr&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #98f5ff;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #4eee94;&quot;&gt;SingleInheritance&lt;/span&gt; : MSInheritanceAttr {&lt;br /&gt;  &lt;span style=&quot;color: #98f5ff;&quot;&gt;let&lt;/span&gt; &lt;span style=&quot;color: #4eee94;&quot;&gt;Spellings&lt;/span&gt; = [&lt;span style=&quot;color: #98f5ff;&quot;&gt;Keyword&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: burlywood;&quot;&gt;&quot;__single_inheritance&quot;&lt;/span&gt;&amp;gt;];&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;During the build, &lt;code&gt;tblgen&lt;/code&gt; is given Attr.td which it parses into a AST and processes:&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;org-src-container&quot;&gt;&lt;pre class=&quot;src src-c++&quot;&gt;OS &amp;lt;&amp;lt; &lt;span style=&quot;color: burlywood;&quot;&gt;&quot;#ifndef LAST_MS_INHERITABLE_ATTR\n&quot;&lt;/span&gt;;&lt;br /&gt;OS &amp;lt;&amp;lt; &lt;span style=&quot;color: burlywood;&quot;&gt;&quot;#define LAST_MS_INHERITABLE_ATTR(NAME)&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: burlywood;&quot;&gt;&quot; MS_INHERITABLE_ATTR(NAME)\n&quot;&lt;/span&gt;;&lt;br /&gt;OS &amp;lt;&amp;lt; &lt;span style=&quot;color: burlywood;&quot;&gt;&quot;#endif\n\n&quot;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #98f5ff;&quot;&gt;Record&lt;/span&gt; *&lt;span style=&quot;color: #4eee94;&quot;&gt;InhClass&lt;/span&gt; = Records.getClass(&lt;span style=&quot;color: burlywood;&quot;&gt;&quot;InheritableAttr&quot;&lt;/span&gt;);&lt;br /&gt;&lt;span style=&quot;color: #98f5ff;&quot;&gt;Record&lt;/span&gt; *&lt;span style=&quot;color: #4eee94;&quot;&gt;InhParamClass&lt;/span&gt; = Records.getClass(&lt;span style=&quot;color: burlywood;&quot;&gt;&quot;InheritableParamAttr&quot;&lt;/span&gt;);&lt;br /&gt;&lt;span style=&quot;color: #98f5ff;&quot;&gt;Record&lt;/span&gt; *&lt;span style=&quot;color: #4eee94;&quot;&gt;MSInheritanceClass&lt;/span&gt; = Records.getClass(&lt;span style=&quot;color: burlywood;&quot;&gt;&quot;MSInheritanceAttr&quot;&lt;/span&gt;);&lt;br /&gt;&lt;span style=&quot;color: #a2cd5a;&quot;&gt;std&lt;/span&gt;::&lt;span style=&quot;color: #98f5ff;&quot;&gt;vector&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #98f5ff;&quot;&gt;Record&lt;/span&gt;*&amp;gt; &lt;span style=&quot;color: #4eee94;&quot;&gt;Attrs&lt;/span&gt; = Records.getAllDerivedDefinitions(&lt;span style=&quot;color: burlywood;&quot;&gt;&quot;Attr&quot;&lt;/span&gt;),&lt;br /&gt;      &lt;span style=&quot;color: #4eee94;&quot;&gt;NonInhAttrs&lt;/span&gt;, &lt;span style=&quot;color: #4eee94;&quot;&gt;InhAttrs&lt;/span&gt;, &lt;span style=&quot;color: #4eee94;&quot;&gt;InhParamAttrs&lt;/span&gt;, &lt;span style=&quot;color: #4eee94;&quot;&gt;MSInhAttrs&lt;/span&gt;;&lt;br /&gt;&lt;span style=&quot;color: deepskyblue;&quot;&gt;for&lt;/span&gt; (&lt;span style=&quot;color: #a2cd5a;&quot;&gt;std&lt;/span&gt;::&lt;span style=&quot;color: #a2cd5a;&quot;&gt;vector&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #98f5ff;&quot;&gt;Record&lt;/span&gt;*&amp;gt;::&lt;span style=&quot;color: #98f5ff;&quot;&gt;iterator&lt;/span&gt; &lt;span style=&quot;color: #4eee94;&quot;&gt;i&lt;/span&gt; = Attrs.begin(), &lt;span style=&quot;color: #4eee94;&quot;&gt;e&lt;/span&gt; = Attrs.end();&lt;br /&gt;     i != e; ++i) {&lt;br /&gt;  &lt;span style=&quot;color: deepskyblue;&quot;&gt;if&lt;/span&gt; (!(*i)-&amp;gt;getValueAsBit(&lt;span style=&quot;color: burlywood;&quot;&gt;&quot;ASTNode&quot;&lt;/span&gt;))&lt;br /&gt;    &lt;span style=&quot;color: deepskyblue;&quot;&gt;continue&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;  &lt;span style=&quot;color: deepskyblue;&quot;&gt;if&lt;/span&gt; ((*i)-&amp;gt;isSubClassOf(InhParamClass))&lt;br /&gt;    InhParamAttrs.push_back(*i);&lt;br /&gt;  &lt;span style=&quot;color: deepskyblue;&quot;&gt;else&lt;/span&gt; &lt;span style=&quot;color: deepskyblue;&quot;&gt;if&lt;/span&gt; ((*i)-&amp;gt;isSubClassOf(MSInheritanceClass))&lt;br /&gt;    MSInhAttrs.push_back(*i);&lt;br /&gt;  &lt;span style=&quot;color: deepskyblue;&quot;&gt;else&lt;/span&gt; &lt;span style=&quot;color: deepskyblue;&quot;&gt;if&lt;/span&gt; ((*i)-&amp;gt;isSubClassOf(InhClass))&lt;br /&gt;    InhAttrs.push_back(*i);&lt;br /&gt;  &lt;span style=&quot;color: deepskyblue;&quot;&gt;else&lt;/span&gt;&lt;br /&gt;    NonInhAttrs.push_back(*i);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;EmitAttrList(OS, &lt;span style=&quot;color: burlywood;&quot;&gt;&quot;INHERITABLE_PARAM_ATTR&quot;&lt;/span&gt;, InhParamAttrs);&lt;br /&gt;EmitAttrList(OS, &lt;span style=&quot;color: burlywood;&quot;&gt;&quot;MS_INHERITABLE_ATTR&quot;&lt;/span&gt;, MSInhAttrs);&lt;br /&gt;EmitAttrList(OS, &lt;span style=&quot;color: burlywood;&quot;&gt;&quot;INHERITABLE_ATTR&quot;&lt;/span&gt;, InhAttrs);&lt;br /&gt;EmitAttrList(OS, &lt;span style=&quot;color: burlywood;&quot;&gt;&quot;ATTR&quot;&lt;/span&gt;, NonInhAttrs);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Something you should probably take note of is how easy the code is to read and understand. This is the rule rather than the exception. In any case, the final result of &lt;code&gt;tblgen&lt;/code&gt; (in this case) is a header file, &lt;code&gt;AttrList.inc&lt;/code&gt;, part of which is reproduced here:&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;org-src-container&quot;&gt;&lt;pre class=&quot;src src-c++&quot;&gt;MS_INHERITABLE_ATTR(MultipleInheritance)&lt;br /&gt;MS_INHERITABLE_ATTR(SingleInheritance)&lt;br /&gt;MS_INHERITABLE_ATTR(UnspecifiedInheritance)&lt;br /&gt;LAST_MS_INHERITABLE_ATTR(VirtualInheritance)&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;I know, it&#39;s not very impressive. But check out what I can do now (this probably doesn&#39;t actually work):&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;org-src-container&quot;&gt;&lt;pre class=&quot;src src-c++&quot;&gt;&lt;span style=&quot;color: deepskyblue;&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: deepskyblue;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #98f5ff;&quot;&gt;char&lt;/span&gt; * &lt;span style=&quot;color: #4eee94;&quot;&gt;MsAttrs&lt;/span&gt;[] = {&lt;br /&gt;&lt;span style=&quot;color: gold;&quot;&gt;#  define&lt;/span&gt; &lt;span style=&quot;color: goldenrod;&quot;&gt;MS_INHERITABLE_ATTR&lt;/span&gt;(&lt;span style=&quot;color: #4eee94;&quot;&gt;Name&lt;/span&gt;) #Name,&lt;br /&gt;&lt;span style=&quot;color: gold;&quot;&gt;#  define&lt;/span&gt; &lt;span style=&quot;color: goldenrod;&quot;&gt;LAST_MS_INHERITABLE_ATTR&lt;/span&gt;(&lt;span style=&quot;color: #4eee94;&quot;&gt;Name&lt;/span&gt;) #Name&lt;br /&gt;&lt;span style=&quot;color: gold;&quot;&gt;#    include&lt;/span&gt; &lt;span style=&quot;color: burlywood;&quot;&gt;&quot;clang/Basic/AttrList.inc&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: gold;&quot;&gt;#  undef&lt;/span&gt; MS_INHERITABLE_ATTR&lt;br /&gt;&lt;span style=&quot;color: gold;&quot;&gt;#  undef&lt;/span&gt; LAST_MS_INHERITABLE_ATTR&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #98f5ff;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: goldenrod;&quot;&gt;main&lt;/span&gt;() {&lt;br /&gt;  &lt;span style=&quot;color: #a2cd5a;&quot;&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; &lt;span style=&quot;color: burlywood;&quot;&gt;&quot;All MS attrs&quot;&lt;/span&gt; &amp;lt;&amp;lt; &lt;span style=&quot;color: #a2cd5a;&quot;&gt;std&lt;/span&gt;::endl;&lt;br /&gt;  &lt;span style=&quot;color: deepskyblue;&quot;&gt;for&lt;/span&gt;( &lt;span style=&quot;color: deepskyblue;&quot;&gt;auto&lt;/span&gt; &lt;span style=&quot;color: #98f5ff;&quot;&gt;attr&lt;/span&gt; : MsAttrs)&lt;br /&gt;    &lt;span style=&quot;color: #a2cd5a;&quot;&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; attr &amp;lt;&amp;lt; &lt;span style=&quot;color: #a2cd5a;&quot;&gt;std&lt;/span&gt;::endl;&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;By listing a bunch of domain-specific &quot;records&quot; in a manner that can be used by the preprocessor, I can now do whatever I like with those records!  I&#39;ve used this to great effect in my own code (from my &lt;a href=&quot;http://worklogassistant.com/&quot;&gt;JIRA&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;http://worklogassistant.com/&quot;&gt;time tracker&lt;/a&gt;). Here is a snippet of &lt;code&gt;JiraTaskAttrs.inc&lt;/code&gt;&amp;nbsp;which contains a list of attributes for a task:&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;org-src-container&quot;&gt;&lt;pre class=&quot;src src-c++&quot;&gt;JIRA_TASK_ATTR(Key)&lt;br /&gt;JIRA_TASK_ATTR(Summary)&lt;br /&gt;JIRA_TASK_ATTR(Description)&lt;br /&gt;JIRA_TASK_ATTR(Type)&lt;br /&gt;JIRA_TASK_ATTR(TypeIconUrl)&lt;br /&gt;JIRA_TASK_ATTR(ProjectKey)&lt;br /&gt;JIRA_TASK_ATTR(ProjectName)&lt;br /&gt;JIRA_TASK_ATTR(ProjectImageUrl)&lt;br /&gt;JIRA_TASK_ATTR(Priority)&lt;br /&gt;JIRA_TASK_ATTR(PriorityIconUrl)&lt;br /&gt;JIRA_TASK_ATTR(Status)&lt;br /&gt;JIRA_TASK_ATTR(StatusIconUrl)&lt;br /&gt;JIRA_TASK_ATTR(Resolution)&lt;br /&gt;JIRA_TASK_ATTR(Security)&lt;br /&gt;JIRA_TASK_ATTR(Assignee)&lt;br /&gt;JIRA_TASK_ATTR(Reporter)&lt;br /&gt;JIRA_TASK_ATTR(Labels)&lt;br /&gt;JIRA_TASK_ATTR(AffectsVersions)&lt;br /&gt;JIRA_TASK_ATTR(FixVersions)&lt;br /&gt;JIRA_TASK_ATTR(Components)&lt;br /&gt;JIRA_TASK_ATTR(TimeEstimated)&lt;br /&gt;JIRA_TASK_ATTR(TimeSpent)&lt;br /&gt;JIRA_TASK_ATTR(TimeRemaining)&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Using this header file, I can generate enumerations:&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;org-src-container&quot;&gt;&lt;pre class=&quot;src src-c++&quot;&gt;&lt;span style=&quot;color: deepskyblue;&quot;&gt;enum&lt;/span&gt; &lt;span style=&quot;color: #98f5ff;&quot;&gt;TaskAttr&lt;/span&gt;{&lt;br /&gt;&lt;span style=&quot;color: gold;&quot;&gt;# define&lt;/span&gt; &lt;span style=&quot;color: goldenrod;&quot;&gt;JIRA_TASK_ATTR&lt;/span&gt;(&lt;span style=&quot;color: #4eee94;&quot;&gt;Name&lt;/span&gt;,...) TaskAttr_##Name,&lt;br /&gt;&lt;span style=&quot;color: gold;&quot;&gt;#   include&lt;/span&gt; &lt;span style=&quot;color: burlywood;&quot;&gt;&quot;JiraTaskAttrs.inc&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: gold;&quot;&gt;# undef&lt;/span&gt; JIRA_TASK_ATTR&lt;br /&gt;  &lt;span style=&quot;color: #4eee94;&quot;&gt;NumTaskAttrs&lt;/span&gt;&lt;br /&gt;};&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Or function definitions:&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;org-src-container&quot;&gt;&lt;pre class=&quot;src src-c++&quot;&gt;&lt;span style=&quot;color: gold;&quot;&gt;#define&lt;/span&gt; &lt;span style=&quot;color: goldenrod;&quot;&gt;IMPL&lt;/span&gt;(&lt;span style=&quot;color: #4eee94;&quot;&gt;Enum&lt;/span&gt;)                                                      \&lt;br /&gt;  &lt;span style=&quot;color: #98f5ff;&quot;&gt;QString&lt;/span&gt;                                                               \&lt;br /&gt;  &lt;span style=&quot;color: #a2cd5a;&quot;&gt;KJiraRepositoryType&lt;/span&gt;::&lt;span style=&quot;color: goldenrod;&quot;&gt;TaskAttr_&lt;/span&gt; ## Enum() &lt;span style=&quot;color: deepskyblue;&quot;&gt;const&lt;/span&gt; {                      \&lt;br /&gt;    &lt;span style=&quot;color: deepskyblue;&quot;&gt;return&lt;/span&gt; toQString(&lt;span style=&quot;color: #a2cd5a;&quot;&gt;model&lt;/span&gt;::&lt;span style=&quot;color: #a2cd5a;&quot;&gt;Task&lt;/span&gt;::getAttrColumnName(&lt;span style=&quot;color: #a2cd5a;&quot;&gt;JiraRepositoryType&lt;/span&gt;::TaskAttr&lt;span style=&quot;color: red;&quot;&gt;_ ## Enum)); \&lt;/span&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: gold;&quot;&gt;#define&lt;/span&gt; &lt;span style=&quot;color: goldenrod;&quot;&gt;JIRA_TASK_ATTR&lt;/span&gt;(&lt;span style=&quot;color: #4eee94;&quot;&gt;Name&lt;/span&gt;,...) IMPL(Name)&lt;br /&gt;&lt;span style=&quot;color: gold;&quot;&gt;#include&lt;/span&gt; &lt;span style=&quot;color: burlywood;&quot;&gt;&quot;common/connections/jira/JiraTaskAttrs.inc&quot;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Here is another example from the same project of how I use this trick to enumerate configuration values: &lt;a href=&quot;http://ix.io/eYI&quot;&gt;Source&lt;/a&gt;, &lt;a href=&quot;http://ix.io/eYK&quot;&gt;C++&lt;/a&gt;. I&#39;ve used this in numerous other places, but this should give you an idea of the types of things that are possible using just the preprocessor and a little forethought.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;outline-2&quot; id=&quot;outline-container-sec-2&quot;&gt;&lt;h2 id=&quot;sec-2&quot;&gt;Conclusion&lt;/h2&gt;&lt;div class=&quot;outline-text-2&quot; id=&quot;text-2&quot;&gt;A good way to become a better craftsman is to learn from others. Software developers are kind of lucky because we have come up sharing the tools of the trade. The open source Clang compiler offers the combined experience of many intelligent software engineers and as a result, there are many tips to be learned that can make you better at your own job. So start reading today!&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;</description><link>http://uint32t.blogspot.com/2014/10/a-walk-through-cool-code-generation.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-6648036378388195732</guid><pubDate>Sat, 24 May 2014 14:33:00 +0000</pubDate><atom:updated>2014-05-24T12:21:16.781-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">build</category><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">ninja</category><category domain="http://www.blogger.com/atom/ns#">scons</category><title>Moving from SCons to CMake</title><description>TL;DR: I&#39;m happy with CMake + Ninja, even though the language is ugly and the speedup is not that impressive.&lt;br /&gt;&lt;br /&gt;I&#39;m not ashamed to admit it: I stayed away from CMake because the language seemed inelegant.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;Elegance and beauty can be defined in many ways but context is apparently important. Maybe this is why the &lt;a href=&quot;https://en.wikipedia.org/wiki/Lisp_(programming_language)&quot; target=&quot;_blank&quot;&gt;most beautiful language&lt;/a&gt; in the world is relegated to being used as an extension language for &lt;a href=&quot;https://www.gnu.org/software/emacs/tour/&quot; target=&quot;_blank&quot;&gt;my editor&lt;/a&gt; rather than to run the world.&lt;br /&gt;&lt;br /&gt;I am currently in the middle of a project moving from SCons to CMake and I am pleasantly surprised at the quick progress. The SCons project has about 3KLOC of SCons build scripts that do everything from generating code for language bindings to building 20-something external C and C++ libraries. My experience with this larger project has also convinced me to move over my &lt;a href=&quot;http://worklogassistant.com/&quot; target=&quot;_blank&quot;&gt;JIRA time tracker&lt;/a&gt;,&amp;nbsp;because of all the other things I &lt;b&gt;should&lt;/b&gt;&amp;nbsp;be doing, the &lt;i&gt;most important thing&lt;/i&gt; is moving over the build system for no particular reason at all.&lt;br /&gt;&lt;br /&gt;SCons served the larger project well when it started. Python was an easy language to learn, if not master and so most people could read the code and make little modifications when they needed to. As the project grew and things got more complicated to manage, we started mimicking other build systems to add features that SCons did not have. The most important feature we cribbed was the &quot;use requirement&quot; feature from Boost Build. In a nutshell, it allows you to attach &quot;arbitrary&quot; requirements to a target that you are consuming. So if you use &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;SomeFunkyDll.dll &lt;/span&gt;in your project, you may want to require that the library clients define &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;SOME_FUNKY_DLL &lt;/span&gt;when they consume it. Automatically doing this in SCons was a big pain in the rear. I don&#39;t need to tell you how we did it because it is not relevant but I wanted to give you an idea of the types of things we found important.&lt;br /&gt;&lt;br /&gt;Another problem that the project started having is once we passed some critical mass of source code, the build seemed to slow down significantly. In the old days, SCons could be slow as molasses because it wanted to be correct over everything else. We tried everything in the &quot;go fast&quot; recommendation list but at best, a no-op build took a long time and this was resulting in too many &lt;a href=&quot;https://sslimgs.xkcd.com/comics/compiling.png&quot; target=&quot;_blank&quot;&gt;sword fights&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Eventually, we got to the point where we thought that working on this project was becoming inefficient so we looked for alternatives. I had always had CMake in the back of my mind as I had actually written my own makefile generator for another project. The architectural separation of specification and the actual build actions allowed optimizations at different levels not unlike a compiler which allowed me to add many more features than I would have been able to had I had to also develop the build action logic.&lt;br /&gt;&lt;br /&gt;I won&#39;t be talking about the larger project yet (maybe ever) but I will talk about my experience moving over &lt;a href=&quot;http://worklogassistant.com/&quot; target=&quot;_blank&quot;&gt;Worklog Assistant&lt;/a&gt;&#39;s build system. Just so that there is a frame of reference:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Number of targets in build (including third-party files): ~1K&lt;/li&gt;&lt;li&gt;Lines of app code (excluding third-party files): ~20K&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;That is, it&#39;s not a huge project.&lt;br /&gt;&lt;br /&gt;A post on build systems can go on forever, but the performance of the build for each of these activities is what actually matters to me when I&#39;m doing my daily work:&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Clean build&lt;/li&gt;&lt;li&gt;Modifying a core header file (aka a file that nearly everything depends on)&lt;/li&gt;&lt;li&gt;Modifying any cpp file in the build&lt;/li&gt;&lt;li&gt;Modifying an important, but not core header file&lt;/li&gt;&lt;li&gt;For some reason this seems to be important when comparing build systems: building when nothing changed. I don&#39;t personally care about this metric.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Each of these will have some sort of relative importance and for me, the activities where build performance matters most are modifying non-core source and header files. The rest have minimal importance.&lt;/div&gt;&lt;/div&gt;&lt;h4&gt;The CMake language, other weirdness and leaky abstractions&lt;/h4&gt;My initial aversion to CMake was likely due to the fact that it was clear to me there would be weird conventions and things that worked kind of differently depending on the backend chosen. I was not wrong in this assumption, but I was wrong in how much they would bother me: not much. Don&#39;t get me wrong, it&#39;s frustrating not completely understanding why changing an &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;add_custom_target&lt;/span&gt; to&lt;span style=&quot;font-family: Georgia, Times New Roman, serif;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;add_custom_command&lt;/span&gt; makes things work &quot;better&quot; with generated files, but by and large, there are few such design bugs.&lt;br /&gt;&lt;br /&gt;The biggest reaction any decent developer probably has when being introduced to CMake is the language. It just looks bad. However, while the language is not efficient by any means, nor is it beautiful, it is predictable and regular which makes it easy to learn. After the initial shock of the aesthetics of the language, you settle into it pretty easily. Thought: perhaps the language being intellectually unappealing encourages the developer to spend as little time in it as possible making him/her quite efficient. Did they learn this from Java? Hmm.&lt;br /&gt;&lt;h4&gt;Different build systems&lt;/h4&gt;&lt;div&gt;I have not launched Visual Studio to do a build since perhaps 2008. There are many reasons to do so however. Comfort and familiarity being one. Incredibuild is another. I think this is the main reason why CMake will eclipse all other C++ build systems: it is a 1-to-N solution. That is, one team&#39;s preference to fulfill their requirements can support the particular preference of N other teams to fulfill theirs. This is not possible with other build systems.&lt;/div&gt;&lt;h4&gt;Third-party library support&lt;/h4&gt;&lt;div&gt;What surprised me the most was how often there were CMake modules available to use for &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;$MY_FAVOURITE_LIBRARY&lt;/span&gt;. This allowed me to treat the building of third-party code as a black box by simply adding a call to &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;add_subdirectory&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;or adding the appropriate path to &lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;CMAKE_MODULE_PATH&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;and adding a call to&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt; find_package.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;CMake would just use the right compiler and the right flags to avoid build incompatibilities. Previously, I&#39;d just write build scripts for the third-party code myself. Win.&lt;/span&gt;&lt;/div&gt;&lt;h4&gt;A highly unscientific test with lots of numbers to look official&lt;/h4&gt;&lt;div&gt;Here is a nice chart:&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://3.bp.blogspot.com/-qHKu3blBKZk/U3-u-iUBEFI/AAAAAAAAAqI/qT3yNVqOXJU/s1600/speedup.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://3.bp.blogspot.com/-qHKu3blBKZk/U3-u-iUBEFI/AAAAAAAAAqI/qT3yNVqOXJU/s1600/speedup.png&quot; height=&quot;409&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;All tests are run with the C++ compiler that comes with Visual Studio 2013 SP1.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;scons -j8: A fairly well-optimized SCons build using many of the tips from the&amp;nbsp;&lt;a href=&quot;http://scons.org/wiki/GoFastButton&quot; target=&quot;_blank&quot;&gt;SCons wiki&lt;/a&gt;,&amp;nbsp;run with 8 parallel jobs. Source lists are built dynamically, using a recursive glob + wildcard filter.&lt;/li&gt;&lt;li&gt;cmake + ninja 1: An unoptimized CMake (2.8.12.2) build using the Ninja stable release from September 2013. Source lists are built with a preprocessing step and some elisp to make maintenance of the preprocessed file easier. See&amp;nbsp;&lt;a href=&quot;https://gist.github.com/kingcheez/0ca4cb133c8705d6e2d6&quot; target=&quot;_blank&quot;&gt;gist&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;cmake + ninja 2: Same as cmake + ninja 1, but configured with CMAKE_LINK_DEPENDS_NO_SHARED=ON&lt;/li&gt;&lt;li&gt;cmake 3.0 + ninja: Same as cmake + ninja 1, but using cmake 3.0&lt;/li&gt;&lt;li&gt;cmake + ninja latest: Same as cmake + ninja 1, but using Ninja from git&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;This looks pretty OK! CMake and Ninja beat SCons. But this is only part of the story. Here is the actual data:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;table border=&quot;1&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; dir=&quot;ltr&quot; style=&quot;border-collapse: collapse; border: 1px solid #ccc; font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;&quot;&gt;&lt;colgroup&gt;&lt;col width=&quot;192&quot;&gt;&lt;/col&gt;&lt;col width=&quot;72&quot;&gt;&lt;/col&gt;&lt;col width=&quot;72&quot;&gt;&lt;/col&gt;&lt;col width=&quot;100&quot;&gt;&lt;/col&gt;&lt;col width=&quot;99&quot;&gt;&lt;/col&gt;&lt;col width=&quot;128&quot;&gt;&lt;/col&gt;&lt;col width=&quot;128&quot;&gt;&lt;/col&gt;&lt;col width=&quot;128&quot;&gt;&lt;/col&gt;&lt;col width=&quot;100&quot;&gt;&lt;/col&gt;&lt;col width=&quot;100&quot;&gt;&lt;/col&gt;&lt;col width=&quot;100&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;Importance&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;Importance&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;scons -j8&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;scons -j8&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;cmake + ninja 1&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;cmake + ninja 1&lt;/td&gt;&lt;td data-sheets-note=&quot;-DCMAKE_LINK_DEPENDS_NO_SHARED=ON  &quot; data-sheets-value=&quot;[null,2,&amp;quot;cmake + ninja 2&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;cmake + ninja 2&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;cmake 3.0 + ninja&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;cmake 3.0 + ninja&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;cmake + ninja latest&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;cmake + ninja latest&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;cmake 1 % speedup&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;cmake 1 % speedup&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;cmake 2 % speedup&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;cmake 2 % speedup&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;cmake 3.0 % speedup&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;cmake 3.0 % speedup&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;cmake + ninja latest % speedup over scons&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;cmake + ninja latest % speedup over scons&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;Clean build&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;Clean build&lt;/td&gt;&lt;td data-sheets-numberformat=&quot;[null,3,&amp;quot;0%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.05]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;5%&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,224]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;224&lt;/td&gt;&lt;td data-sheets-formula=&quot;=279&quot; data-sheets-value=&quot;[null,3,null,279]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;279&lt;/td&gt;&lt;td data-sheets-formula=&quot;=264&quot; data-sheets-value=&quot;[null,3,null,264]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;264&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,266]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;266&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,261]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;261&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.2455357142857142]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-24.55%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.1785714285714286]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-17.86%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.1875]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-18.75%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.1651785714285714]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-16.52%&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;Touch String.hpp and rebuild&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;Touch core header file and rebuild&lt;/td&gt;&lt;td data-sheets-numberformat=&quot;[null,3,&amp;quot;0%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.05]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;5%&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,165]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;165&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,178]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;178&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,174]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;174&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,180]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;180&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,175]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;175&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.07878787878787885]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-7.88%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.05454545454545445]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-5.45%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.09090909090909083]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-9.09%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.06060606060606055]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-6.06%&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;Touch String.cpp and rebuild&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;Touch a source file and rebuild&lt;/td&gt;&lt;td data-sheets-numberformat=&quot;[null,3,&amp;quot;0%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.5]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;50%&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,46]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;46&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,35]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;35&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,35]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;35&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,35]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;35&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,35]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;35&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.23913043478260865]&quot; style=&quot;color: lime; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;23.91%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.23913043478260865]&quot; style=&quot;color: lime; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;23.91%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.23913043478260865]&quot; style=&quot;color: lime; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;23.91%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.23913043478260865]&quot; style=&quot;color: lime; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;23.91%&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;Touch Controller.hpp and rebuild&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;Touch an arbitrary non-core header file and rebuild&lt;/td&gt;&lt;td data-sheets-numberformat=&quot;[null,3,&amp;quot;0%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.4]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;40%&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,60]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;60&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,68]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;68&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,65.5]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;65.5&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,66]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;66&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,65]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;65&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.1333333333333333]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-13.33%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.09166666666666656]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-9.17%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.10000000000000009]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-10.00%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,-0.08333333333333326]&quot; style=&quot;color: red; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;-8.33%&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;Do-nothing and build&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;Do-nothing and build&lt;/td&gt;&lt;td data-sheets-numberformat=&quot;[null,3,&amp;quot;0%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;0%&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,10]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;10&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,0.5]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;0.5&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,0.5]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;0.5&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,0.2]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;0.2&lt;/td&gt;&lt;td data-sheets-value=&quot;[null,3,null,0.44]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;0.44&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.95]&quot; style=&quot;color: lime; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;95.00%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.95]&quot; style=&quot;color: lime; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;95.00%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.98]&quot; style=&quot;color: lime; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;98.00%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=( 1-R[0]C[-4]/R[0]C3 )&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.956]&quot; style=&quot;color: lime; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;95.60%&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td data-sheets-value=&quot;[null,2,&amp;quot;Weighted average&amp;quot;]&quot; style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;Weighted average&lt;/td&gt;&lt;td data-sheets-formula=&quot;=SUM(R[-6]C[0]:R[-2]C[0])&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,1]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;100%&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td style=&quot;padding: 2px 3px 2px 3px; vertical-align: bottom;&quot;&gt;&lt;/td&gt;&lt;td data-sheets-formula=&quot;=sumproduct(R[-6]C[0]:R[-2]C[0],R2C2:R6C2)/sum(R2C2:R6C2)&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.05001570440429135]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;5.00%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=sumproduct(R[-6]C[0]:R[-2]C[0],R2C2:R6C2)/sum(R2C2:R6C2)&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.07124270656879354]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;7.12%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=sumproduct(R[-6]C[0]:R[-2]C[0],R2C2:R6C2)/sum(R2C2:R6C2)&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.06564476284584975]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;6.56%&lt;/td&gt;&lt;td data-sheets-formula=&quot;=sumproduct(R[-6]C[0]:R[-2]C[0],R2C2:R6C2)/sum(R2C2:R6C2)&quot; data-sheets-numberformat=&quot;[null,3,&amp;quot;0.00%&amp;quot;,1]&quot; data-sheets-value=&quot;[null,3,null,0.07494265245623943]&quot; style=&quot;padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;&quot;&gt;7.49%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;The Ninja build sees only a significant improvement over SCons when modifying source files but it has a terrible result when it comes to touching header files. I have my own theories as to why, but running ninja -d stats showed that loading the dependency file was the biggest slowdown.&lt;br /&gt;&lt;br /&gt;The weighted average is computed using the &quot;importance&quot; column. I think touching source files should perhaps have a higher importance than I&#39;ve given it above. Do I really edit header files as often as source files? I don&#39;t have the answer to that so as a proxy, I just ran a simple script counting how many header files vs source files were touched in a 6 month period and applied the ratio as a weight. My gut feeling is that I probably spend more time editing source files than header files.&lt;br /&gt;&lt;h4&gt;Conclusions&lt;/h4&gt;&lt;div&gt;Not as clear cut a win as I had hoped: a well-optimized SCons build can still be faster for some sizes of projects and it is possibly more correct. However, the equivalent SCons build does require more maintenance to provide the same features as one in CMake. I found that compiler/toolchain support is much better with CMake than with SCons and I write less code to do the same (complex) thing. Occasionally, CMake&#39;s abstractions leak making it awkward to do simple things like generating files, which are easy with SCons. On the other hand, CMake makes it easy to add per-file compile options which are difficult with SCons.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since the performance for this particular example is roughly equal, I have to choose the system that makes me feel more productive. And by that metric, CMake + Ninja make me &quot;feel&quot; more productive only because Ninja starts building immediately.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What matters even more: the SCons community has always been small. The CMake community on the other hand is huge in comparison and is only growing. I expect performance to improve and more backend options to become available that improve performance.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I had about 4 or 5 years of SCons experience that went into the build for this project. This means there are a lot of little performance tricks I applied and as my experience with CMake is not nearly as long, it isn&#39;t a fair comparison. I should be ashamed of expecting a free speedup, but the speedup I did see for an important use case makes me feel as if it was worth it.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On the upside, I no longer have to wait for SCons to start building something after hitting compile.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Have you transitioned to/from CMake? I&#39;d be curious to hear about your experiences.&lt;/div&gt;&lt;h4&gt;Interesting links&lt;/h4&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://scons.org/&quot; target=&quot;_blank&quot;&gt;SCons&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://parts.tigris.org/&quot; target=&quot;_blank&quot;&gt;Parts&lt;/a&gt;&amp;nbsp;- A promising extension to SCons&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://martine.github.io/ninja/&quot; target=&quot;_blank&quot;&gt;Ninja&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://neugierig.org/software/chromium/notes/2011/02/ninja.html&quot; target=&quot;_blank&quot;&gt;Ninja, a new build system&lt;/a&gt;&amp;nbsp;- Blog post about the birth of Ninja&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://code.google.com/p/gyp/&quot; target=&quot;_blank&quot;&gt;GYP: Generate Your Projects&lt;/a&gt;&amp;nbsp;- Yet another makefile generator&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;</description><link>http://uint32t.blogspot.com/2014/05/moving-from-scons-to-cmake.html</link><author>noreply@blogger.com (Unknown)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-qHKu3blBKZk/U3-u-iUBEFI/AAAAAAAAAqI/qT3yNVqOXJU/s72-c/speedup.png" height="72" width="72"/><thr:total>6</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-7450464445033537187</guid><pubDate>Mon, 12 May 2014 23:52:00 +0000</pubDate><atom:updated>2014-05-12T19:54:27.725-04:00</atom:updated><title>So I was right about the vector, wrong about the players</title><description>You will cringe hard when you read how I &lt;a href=&quot;https://web.archive.org/web/20040223173430/http://www.sohailsomani.com/Professional/dotNet.html&quot;&gt;wrote about C#&lt;/a&gt; many years ago but I had honestly expected &lt;a href=&quot;http://www.wired.com/2014/05/oracle-copyright&quot;&gt;this&lt;/a&gt; to happen to C#, not Java. Maybe having C# as a ISO standard actually had some benefits.&lt;br /&gt;&lt;br /&gt;Will there be a Heartbleed-like crisis where these ideas will cause a reckoning for the industry? As I understand it, the licensing for implementing the x86/x86_64 ISAs reached monopoly level years ago, actively shutting out competition. The main hardware innovation is now coming from mobile where x86 can&#39;t yet compete. PC sales have been leveling out ever since the introduction of iStuff. I don&#39;t think the three are correlated, but it is interesting.&lt;br /&gt;&lt;br /&gt;PS: If you still want to be friends, do not read the rest of the content on that first link. Oh man.&lt;br /&gt;&lt;br /&gt;</description><link>http://uint32t.blogspot.com/2014/05/so-i-was-right-about-vector-wrong-about.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-2924948835972302109</guid><pubDate>Thu, 21 Mar 2013 15:12:00 +0000</pubDate><atom:updated>2014-04-14T08:46:44.686-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">c++0x</category><category domain="http://www.blogger.com/atom/ns#">c++1x</category><title>Design by committee works slowly</title><description>The &lt;a href=&quot;http://isocpp.org/files/papers/N3559.pdf&quot; target=&quot;_blank&quot;&gt;latest draft&lt;/a&gt; for polymorphic lambda expressions, which I &lt;a href=&quot;http://uint32t.blogspot.ca/2009/05/using-c0x-lambda-to-replace-boost-bind.html&quot; target=&quot;_blank&quot;&gt;advocated for&lt;/a&gt; in a post about 3 thousand years ago, is a step in the right direction. I greatly appreciate the time that the authors are taking to push C++ forward. I know they do it on a volunteer basis and I believe their passion for it makes C++ one of the best languages to use for a variety of projects. On reading the draft though, I&#39;m still a little underwhelmed.&lt;br /&gt;&lt;br /&gt;Lambda expressions are anonymous functions that are common in languages with first-class functions like Lisp. Roughly, the language gives you the ability to create functions &quot;at runtime&quot; which allows you to store data and other state. Once this is possible, anything is possible. You can read more about anonymous functions&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Anonymous_function&quot; target=&quot;_blank&quot;&gt;at Wikipedia&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;When a programmer uses anonymous functions, he or she is not doing it for a technical reason (i.e., performance) They are doing it for one or all of the following reasons:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Lexical locality: The data that the anonymous function will be operating on is somewhere nearby and we just need to do a little transform on it to make it useful to something else which is also nearby.&lt;/li&gt;&lt;li&gt;Readability: x =&amp;gt; 2*x+y is much easier to read and understand than MyFunctor f(y) because you need to go look up the definition of MyFunctor.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In x =&amp;gt; 2*x+y, you can see that the &#39;y&#39; value must come from somewhere else in the function: capturing data in lexical scope is an important part of anonymous functions. This is the reason why MyFunctor takes in &#39;y&#39; as a parameter.&lt;br /&gt;&lt;br /&gt;Anyway, as my post tried to explain, one of the main problems is the ridiculous verbosity implicit in monomorphic lambda expressions. By allowing polymorphic lambdas, the verbosity has a chance to be reduced or even eliminated to the simplest possible thing. The latest draft makes an &quot;auto&quot; necessary on lambda expression parameters.&lt;br /&gt;&lt;br /&gt;To recap, C++11 lambda expressions transform a statement like:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; [](double slope, double intercept, double x){ return slope * x + intercept; }&lt;br /&gt;&lt;br /&gt;into a function object not completely unlike:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; struct LOL&lt;br /&gt;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; double operator()(double slope, double intercept, double x){ return ... ;}&lt;br /&gt;&amp;nbsp; &amp;nbsp; };&lt;br /&gt;&lt;br /&gt;Most lambda expressions will only ever be used with one set of parameter types and in one situation so it is not hard to understand why this is one acceptable syntax. However, languages like C# have much more concise syntax for the above case:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp;slope,intercept,x =&amp;gt; slope * x + intercept&lt;br /&gt;&lt;br /&gt;The compiler figures out the types since it is a statically typed language and everyone is happy.&lt;br /&gt;&lt;br /&gt;Before lambda expressions, in C++, we might have written:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; namespace bl = boost::lambda;&lt;br /&gt;&amp;nbsp; &amp;nbsp; ...&amp;nbsp; &amp;nbsp; bl::_1*bl::_2 + bl::_3 ...&lt;br /&gt;&lt;br /&gt;My goal for C++ lambda expressions would be to &lt;b&gt;never&lt;/b&gt; use any of the Boost lambda libraries again, as useful and awesome as they are. With the new draft, the C++11 version becomes:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; [](auto slope, auto intercept, auto x){ return slope*x + intercept; }&lt;br /&gt;&lt;br /&gt;As you can see, the above Boost Lambda form is arguably still preferable to the draft version of polymorphic functions just on length alone. And although it &lt;b&gt;is&lt;/b&gt; longer, it is slightly easier to read and understand because of the named parameters. But why can&#39;t we spoil ourselves? There aren&#39;t too many technical tricks required to automatically turn:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; [](slope,intercept,x){ return slope*x + intercept; }&lt;br /&gt;&lt;br /&gt;into the same form behind the scenes.&lt;br /&gt;&lt;br /&gt;In my humble opinion, the auto actually adds nothing to readability and takes it away because I am required to read more to understand what is going on. Multiply this by thousands of expressions and multiple projects and it is just another thing I have to skip over. There is actually very little reason to require auto. With this extension, it is &lt;b&gt;still&lt;/b&gt; easier to use Boost Lambda&lt;br /&gt;&lt;br /&gt;The 5 people who voted &quot;strongly against&quot; making auto optional should rethink their votes. This is the best chance we have of getting it right the &lt;strike&gt;first&lt;/strike&gt;second time.</description><link>http://uint32t.blogspot.com/2013/03/design-by-committee-works-slowly.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-5053012611972276167</guid><pubDate>Sun, 29 May 2011 21:13:00 +0000</pubDate><atom:updated>2011-05-29T17:13:55.220-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">bitcoin</category><category domain="http://www.blogger.com/atom/ns#">i&#39;m on the list now</category><title>Learning about Bitcoin or why I&#39;ll never use Bitcoin</title><description>&lt;p style=&quot;clear: both&quot;&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Bitcoin&quot; title=&quot;&quot; target=&quot;_blank&quot;&gt;Bitcoin&lt;/a&gt; is quite a promising e-currency. Created by some-guy-we-don&#39;t-really-know-or-a-double-agent-of-some-kind-who-is-probably-quite-Bitcoin-rich-now, it has some very useful properties:&lt;/p&gt;&lt;ol style=&quot;clear: both&quot;&gt;&lt;li&gt;Creation of the money is an implicit and transparent agreement between users. That is, there is no centralized issuing authority and there is a finite quantity. Almost like gold.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It is completely electronic and therefore very cheap to transfer. As a result, transaction fees are &quot;low&quot;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Transactions are anonymized, yet completely public to avoid against double-spending.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Some crypto stuff to make sure it is as secure as it can be today&lt;/li&gt;&lt;/ol&gt;&lt;p style=&quot;clear: both&quot;&gt;The main desired outcome of a currency with these rules is autonomy of the currency from the somewhat arbitrary influence of centralized planners.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;strong&gt;&lt;u&gt;How you are supposed to use Bitcoin&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;So how do you use Bitcoin (BTC) as a consumer or vendor? Let us assume that you already have some BTC in your account.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;div&gt;&lt;ol style=&quot;clear: both&quot;&gt;&lt;li&gt;Visit place of business&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Locate item of interest which costs 0.02 BTC&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Go to cashier&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Pull out smart phone with your Bitcoin wallet or some kind of link to your Bitcoin wallet&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Use QR-code at register to find vendor&#39;s payment address. This address will likely be generated at the point of purchase&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Send Bitcoin to that address from your Bitcoin wallet&lt;/li&gt;&lt;li&gt;The cashier and network verifies your payment (speed depends on transaction fee) and you go on your way&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;div&gt;This is how it would work today if a business accepted BTC. I expect that if I am wrong and if Bitcoin does indeed take off, there will be clearing houses to speed up transactions like these. I think that these confirmations will necessarily be done outside the network but eventually, the network will also validate these which will be the final settlement step.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;This exchange is appealing for various reasons. My favourite one is that the users of the system itself benefit by confirming transactions. That is, you can make Bitcoin just by verifying transactions.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;strong&gt;&lt;u&gt;Bitcoin Wallet&lt;/u&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;It is probably useful to discuss where Bitcoins are stored. This location, a file on your hard disk, is called a wallet. It consists of a set of private keys that correspond to each address generated as in the above scenario. This is your vault. If it is stolen in unencrypted form, your money is probably as as good as gone. But the coolest part is that if you have a backup and it was encrypted, you simply transfer the money to an account in a new wallet before the thieves are able to crack the encryption and almost by magic, your money is back again.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;u&gt;Anonymous vs Anonymized&lt;/u&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Earlier, I said that transactions are &lt;em&gt;anonymized. &lt;/em&gt;This is different from them being &lt;em&gt;anonymous &lt;/em&gt;because an anonymizing technology does not imply anonymity. A transaction being anonymous means untraceable which is something that is quite easy to disprove in the BTC world.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Let&#39;s start at the beginning. How do you get BTC? There are a couple of ways. One way involves a lot of geekery and stuff that very few people have time for. This is called Bitcoin mining. For most people, just outright buying BTC like they buy USD is the most convenient. Currency is a proxy for labour so it is fine to buy BTC. As the market will continue to be volatile due to the simultaneous debasing of the USD, demand-side pressure as well as the continuous creation of BTC, I would spread out bigger purchases over a few months.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;A convenient way to buy BTC is through an exchange. So let us walk through that process:&lt;br /&gt;&lt;ol style=&quot;clear: both&quot;&gt;&lt;li&gt;Create an account with a BTC exchange. I used &lt;a href=&quot;http://bitcoinmarket.com&quot; title=&quot;&quot; target=&quot;_blank&quot;&gt;Bitcoin Market&lt;/a&gt;. This requires you to give them two things: an email address and a Bitcoin payment address. Notice how your email address is tied to your BTC address.&lt;/li&gt;&lt;li&gt;Figure out the trade you want to make. I used BMBTC for PPUSD where BM = Bitcoin Market and PP = PayPal.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Execute the trade by making a payment to some email address on PayPal.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;When I executed this process, it took a total of 15 minutes for the trade to complete but it was a full hour before the money was in my actual wallet and verified by the network. You must note that this is the equivalent of someone on the other side of the world paying me $10 and someone delivering that $10 to me personally. Not to a bank account, not a promise for $10, but cold hard cash to me personally.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Notice that the process of conveniently buying BTC itself has multiple weak links:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ol style=&quot;clear: both&quot;&gt;&lt;li&gt;Your email address is tied to a Bitcoin address by Bitcoin Market&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Paypal knows who you are definitively through the use of your credit card&lt;/li&gt;&lt;li&gt;Some random dude knows you bought some BTC&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;To avoid leaking too much information, you can create a new receiving address for every trade and update it on the Bitcoin Market. Note that Bitcoin Market has full trade information and PayPal has amount information. To reduce the risk there, you can use anonymizing email services or a special email just for Bitcoin purchases.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;em&gt;&lt;/em&gt;&lt;br /&gt;The main point is that once you use a credit card or a personal email address, your anonymity is compromised.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;That&#39;s not such a big deal, to be honest. After all, you already trust a lot of people with your information online.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;strong&gt;&lt;u&gt;De-anonymizing the transactions&lt;/u&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If the seller of the BTC was interested in which address bought the BTC through the exchange, s/he would just track the blocks for the specific amount.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;When I purchased my BTC, I chose 2 BTC to see how difficult it would be to find in the block explorer. It was pretty easy! Why? Because I knew there would be three related transactions: one for 2, one for 1.99 and one for 0.01 (transaction fee by exchange.) The seller would know this as well.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;So all I did was wait for a few blocks to come through the explorer and opened them all up in a browser tab and searched for 1.99. It took less than a minute.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;So now, the seller of the BTC has tied my name (through Paypal) to an address.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;You may be interested in the &lt;a href=&quot;http://blockexplorer.com/tx/ac6276792391e57f6fb55c62e78bce435944b7eb6e475d59fc6e539f0b9f7a6f&quot; title=&quot;&quot; target=&quot;_blank&quot;&gt;actual transaction&lt;/a&gt; as currently being confirmed by computers worldwide. Because of this decentralized confirmation, it is now impossible for the seller to re-sell the same BTC to someone else.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;strong&gt;&lt;u&gt;Using my Bitcoin or why I&#39;ll never use it&lt;/u&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;Can you figure out what I did with my BTC? Actually, you have all the information you need in this blog post. Once you figure it out, you&#39;ll understand why I&#39;ll never use it. &lt;strong&gt;&lt;em&gt;The first person to add a comment with the right answer and their Bitcoin receiving address will get the remainder of my balance transferred to their Bitcoin address&lt;/em&gt;&lt;/strong&gt;. It&#39;s not much, but I probably won&#39;t use it...&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;u&gt;How to stay anonymous&lt;/u&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;There are ways to &lt;a href=&quot;https://en.bitcoin.it/wiki/Anonymity#Staying_anonymous&quot; title=&quot;&quot; target=&quot;_blank&quot;&gt;stay anonymous&lt;/a&gt; by obfuscating the block chain. However, this is not right. For a currency to be useful, its primitive form must be practically anonymous and not just anonymizing.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;strong&gt;&lt;u&gt;How I&#39;d change Bitcoin&lt;/u&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;My main issues with Bitcoin:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;clear: both&quot;&gt;&lt;li&gt;Not anonymous: Identity &quot;anchors&quot; are very easy to establish by transacting with people as described above. This leads to a situation where an attacker can find out what you spend your BTC on for their own nefarious purposes.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The currency has no decay value. That is, it can be hoarded without consequence. I would like BTC to expire so that the currency can keep circulating. This maintains the value of the currency but prevents hoarding. The block chain has enough information to do this. Miners should be interested in this because it means they can continue to mine forever and keep a healthy Bitcoin economy.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;I think the anonymity problem is the most hard to solve. I am only concerned with the ability to transfer coin between my own accounts &lt;em&gt;easily &lt;/em&gt;without notifying anyone else. If some way could be devised to solve these problems, goodbye centralized currencies.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/p&gt;&lt;br class=&#39;final-break&#39; style=&#39;clear: both&#39; /&gt;</description><link>http://uint32t.blogspot.com/2011/05/learning-about-bitcoin-or-why-i-never.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>7</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-4974156190839098977</guid><pubDate>Wed, 27 Apr 2011 00:13:00 +0000</pubDate><atom:updated>2011-04-26T20:13:59.324-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">code</category><category domain="http://www.blogger.com/atom/ns#">dependencyinjection</category><category domain="http://www.blogger.com/atom/ns#">di</category><title>Deconstructing a dependency injection-driven application</title><description>&lt;p style=&quot;clear: both&quot;&gt;I&#39;ve been using my &lt;a href=&quot;https://bitbucket.org/cheez/dicpp/wiki/Home&quot; target=&quot;_blank&quot;&gt;C++ dependency injection library&lt;/a&gt; for a project in the last year and it&#39;s gone pretty well. There are a lot of rough edges but I thought it could be interesting to the 3 of you still subscribed to this blog to de-construct the stock quote application.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;strong&gt;About the application&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;The &lt;a href=&quot;https://bitbucket.org/cheez/dicpp/src/f35b101eff14/lib/examples/stockquote/&quot; target=&quot;_blank&quot;&gt;example&lt;/a&gt; itself is pretty straight forward. You have a choice of 3 stock quote providers: Yahoo!, static and phone. You choose one and ask for a stock quote. Magic happens and your stock quote arrives.&lt;strong&gt;&lt;em&gt;&lt;br /&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;strong&gt;Example session (with some debug output)&lt;/strong&gt;&lt;/p&gt;&lt;pre style=&quot;clear: both&quot;&gt;Welcome to the DI Stock Quote App. Simplifying and complicating software development since 2010.&lt;br /&gt;Which stock quote service would you like to use?&lt;br /&gt;1: static&lt;br /&gt;2: phone&lt;br /&gt;3: yahoo&lt;br /&gt;Enter your choice (1-3) and press enter: 3&lt;br /&gt;You chose: yahoo&lt;br /&gt;[DICPP]: No scope constructing: di::type_key&amp;lt;YahooStockQuoteService, void&amp;gt;&lt;br /&gt;[DICPP]: Constructing: di::type_key&amp;lt;di::typed_provider&amp;lt;HttpDownloadService&amp;gt;, void&amp;gt;&lt;br /&gt;[DICPP]: Completed constructing: di::type_key&amp;lt;di::typed_provider&amp;lt;HttpDownloadService&amp;gt;, void&amp;gt; with address: 0x100750&lt;br /&gt;Stock symbol (type quit to quit): goog&lt;br /&gt;[DICPP]: No scope constructing: di::type_key&amp;lt;HttpDownloadService, void&amp;gt;&lt;br /&gt;[DICPP]: Constructing: di::type_key&amp;lt;boost::asio::io_service, void&amp;gt;&lt;br /&gt;[DICPP]: Singleton: constructing: di::type_key&amp;lt;boost::asio::io_service, void&amp;gt;&lt;br /&gt;[DICPP]: Completed constructing: di::type_key&amp;lt;boost::asio::io_service, void&amp;gt; with address: 0x1008a0&lt;br /&gt;Current price for goog: 532.82&lt;br /&gt;Stock symbol (type quit to quit): quit&lt;br /&gt;&lt;/pre&gt;&lt;p style=&quot;clear: both&quot;&gt;See how the construction of the HTTP service is automatically delayed until actually needed. This is done through a concept called a &quot;provider&quot; which is basically an automatically generated factory.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;About Dependency Injection&lt;/strong&gt;&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;A really good introduction to the dependency injection technique as implemented by &lt;a href=&quot;http://code.google.com/p/google-guice/&quot; target=&quot;_blank&quot;&gt;Guice&lt;/a&gt; can be found &lt;a href=&quot;http://www.youtube.com/watch?v=hBVJbzAagfs&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;. It&#39;s probably one of my favourite tech talks of all time.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;Anyway, to refresh your memory, here are some of the main benefits of the technique used in Guice:&lt;/p&gt;&lt;ul style=&quot;clear: both&quot;&gt;&lt;li&gt;Object construction and lifecycle management is mostly handled for you.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Less boilerplate.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Makes code more testable.&lt;/li&gt;&lt;li&gt;Scopes (~object creation/lifecycle) can be customized by the user.&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;clear: both&quot;&gt;In short: a lot of the time, you no longer need to allocate objects or pass some object unused down multiple layers of functions or object constructors just to use them once way deep down in some code.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;strong&gt;Magic!&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I don&#39;t really recall how it is done in Guice but in the C++ library linked above, this magic is driven by a type registry which recursively registers constructor arguments as well as user customizations.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;In extreme cases, you can initialize an entire application with a few lines of code:&lt;/p&gt;&lt;pre style=&quot;clear: both&quot;&gt;  di::registry r;&lt;br /&gt;  r.add( r.type&amp;lt;MyApplication&amp;gt;() );&lt;br /&gt;  r.construct&amp;lt;shared_ptr&amp;lt;MyApplication&amp;gt;&amp;gt;()-&amp;gt;execute();&lt;/pre&gt;&lt;p style=&quot;clear: both&quot;&gt;This constructs the type registry which is a kind of factory. There is a mini-DSL for describing how you want the registry to handle the type. More on this later. In this case, we are asking the registry to &quot;learn&quot; about the MyApplication type as well as all objects that are required for constructing MyApplication.&lt;br /&gt;&lt;br /&gt;&quot;Pish-posh&quot;, you say. &quot;MyApplication has a 0-arg constructor. I could do that in my sleep.&quot;&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;Would you be surprised if I said that the MyApplication type actually has 3 arguments?&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;Well, the above is almost what the StockQuote application looks like. Here is the main function for the stock quote example:&lt;/p&gt;&lt;pre style=&quot;clear: both&quot;&gt;di::injector inj;&lt;br /&gt;inj.install( StockQuoteAppModule() );&lt;br /&gt;&lt;/pre&gt;&lt;pre style=&quot;clear: both&quot;&gt;StockQuoteApp &amp;amp; app = inj.construct&amp;lt;StockQutoeApp&amp;amp;&amp;gt;(); // lifetime&lt;br /&gt;app.execute();&lt;/pre&gt;&lt;p style=&quot;clear: both&quot;&gt;And here is the constructor for the StockQuoteApp type:&lt;/p&gt;&lt;pre style=&quot;clear: both&quot;&gt;DI_CONSTRUCTOR ( StockQuoteApp ,&lt;br /&gt;                ( boost :: shared_ptr &amp;lt; UserInterface &amp;gt;  ui , &lt;br /&gt;                 boost :: shared_ptr &amp;lt; StockQuoteServiceFactory &amp;gt;  factory ));&lt;/pre&gt;&lt;p style=&quot;clear: both&quot;&gt;When we ask the &quot;injector&quot; to construct the StockQuoteApp instance, it automatically creates the UserInterface as well as the StockQuoteServiceFactory instance.&lt;br /&gt;&lt;br /&gt;The di::injector type is just a thin wrapper around the registry so you can treat it as such. The only thing it really provides is a little bit of syntax to allow you to create modules in a similar manner as Guice. The guts of StockQuoteAppModule accept a registry as a parameter and register the various types. You can see the mini-DSL referred to earlier:&lt;/p&gt;&lt;pre style=&quot;clear: both&quot;&gt;void&lt;br /&gt;StockQuoteAppModule::operator()( di::registry &amp;amp; r ) const&lt;br /&gt;{&lt;br /&gt;  // In each module we define the module&#39;s root objects, in this case,&lt;br /&gt;  // StockQuoteApp as well as implementations/specializations of any&lt;br /&gt;  // abstract classes. For example, UserInterface is an ABC and we choose&lt;br /&gt;  // the console-based UI here.&lt;br /&gt;&lt;br /&gt;  r.add(&lt;br /&gt;    r.type&amp;lt;StockQuoteApp&amp;gt;()&lt;br /&gt;    .in_scope&amp;lt;di::scopes::singleton&amp;gt;() // The reason we can request a reference in the main function!&lt;br /&gt;    );&lt;br /&gt;&lt;br /&gt;  r.add(&lt;br /&gt;    r.type&amp;lt;UserInterface&amp;gt;()&lt;br /&gt;    .implementation&amp;lt;ConsoleInterface&amp;gt;()&lt;br /&gt;    .in_scope&amp;lt;di::scopes::singleton&amp;gt;()&lt;br /&gt;    );&lt;br /&gt;&lt;br /&gt;  r.add(&lt;br /&gt;    r.type&amp;lt;StockQuoteServiceFactory&amp;gt;()&lt;br /&gt;    .implementation&amp;lt;StaticStockQuoteServiceFactory&amp;gt;()&lt;br /&gt;    .in_scope&amp;lt;di::scopes::singleton&amp;gt;()&lt;br /&gt;    );&lt;br /&gt;&lt;br /&gt;  r.add(&lt;br /&gt;    r.type&amp;lt;HttpDownloadService&amp;gt;()&lt;br /&gt;    .implementation&amp;lt;AsioHttpDownloadService&amp;gt;()&lt;br /&gt;    );&lt;br /&gt;&lt;br /&gt;  r.add(&lt;br /&gt;    r.type&amp;lt;boost::asio::io_service&amp;gt;()&lt;br /&gt;    .in_scope&amp;lt;di::scopes::singleton&amp;gt;()&lt;br /&gt;    );&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p style=&quot;clear: both&quot;&gt;As you can see, the mini-DSL (&lt;a href=&quot;https://bitbucket.org/cheez/dicpp/src/f35b101eff14/include/di/detail/registration_builder.hpp&quot; target=&quot;_blank&quot;&gt;ugly, ugly, ugly, details&lt;/a&gt;) describes a few things:&lt;/p&gt;&lt;ul style=&quot;clear: both&quot;&gt;&lt;li&gt;Default implementations for various interface classes. See UserInterface and ConsoleInterface, for example.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Life-cycle management. Singleton is mostly used here but you can also have HTTP-session scopes, thread-local scopes or no scopes (as in HttpDownloadService).&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;clear: both&quot;&gt;What this means is wherever a type T with a DI_CONSTRUCTOR macro is registered, the registry will use these rules described by the DSL to construct any arguments to T.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;strong&gt;Providers&lt;/strong&gt;&lt;br /&gt;In this library, there is a concept of a type called a provider whose sole responsibility it is to construct objects (usually within the constraints of a scope). In the app session above, I pointed out how the HTTP download service is not instantiated until it is actually needed. This is done via a provider. You can see the &lt;a href=&quot;https://bitbucket.org/cheez/dicpp/src/f35b101eff14/lib/examples/stockquote/YahooStockQuoteService.hpp&quot; target=&quot;_blank&quot;&gt;YahooStockQuoteService&lt;/a&gt; has a constructor which accepts a provider and a &lt;a href=&quot;https://bitbucket.org/cheez/dicpp/src/f35b101eff14/lib/examples/stockquote/YahooStockQuoteService.cpp&quot; target=&quot;_blank&quot;&gt;function&lt;/a&gt; which makes use of it.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;That should be enough information to peruse the &lt;a href=&quot;https://bitbucket.org/cheez/dicpp/src/f35b101eff14/lib/examples/stockquote/&quot; target=&quot;_blank&quot;&gt;example&lt;/a&gt; itself. Check the &lt;a href=&quot;https://bitbucket.org/cheez/dicpp/src/f35b101eff14/lib/examples/stockquote/README&quot; target=&quot;_blank&quot;&gt;README&lt;/a&gt; as there are a couple of interesting exercises you can try.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;By the way, this requires a Boost checkout with a built version of Boost Build. I apologize if you can&#39;t get it to build on checkout, but I haven&#39;t really focused on having other people use it!&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;Comments and thoughts welcome.&lt;/p&gt;&lt;br class=&#39;final-break&#39; style=&#39;clear: both&#39; /&gt;</description><link>http://uint32t.blogspot.com/2011/04/deconstructing-dependency-injection.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-8581683943365557418</guid><pubDate>Tue, 29 Mar 2011 15:55:00 +0000</pubDate><atom:updated>2011-03-29T11:55:19.075-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">boost</category><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">clang</category><title>C++ has not jumped the shark</title><description>&lt;p style=&quot;clear: both&quot;&gt;I love &lt;a href=&quot;http://www.johndcook.com/&quot; target=&quot;_blank&quot;&gt;John&#39;s blog&lt;/a&gt;. If you are not subscribed, you should be subscribed. He is one of my favourite bloggers as I actually learn something when he posts.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;Somehow, I managed to miss his post on &lt;a href=&quot;http://www.johndcook.com/blog/2009/08/18/has-cpp-jumped-the-shark/&quot; target=&quot;_blank&quot;&gt;C++ going about as far as it can go&lt;/a&gt; in its evolution. Fortunately, it showed up on YCombinator News a few days back so I got the chance to catch up.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;From my reading, John is concerned about the following:&lt;/p&gt;&lt;ul style=&quot;clear: both&quot;&gt;&lt;li&gt;The language has stopped evolving because it is too long between revisions of the standard.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;He doesn&#39;t need anything new therefore new features are not useful for him.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Something about concepts.&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;clear: both&quot;&gt; I don&#39;t intend on refuting or accepting those points as that&#39;s not what this is about. I just wanted to give a short summary. Also, I&#39;m not really that interested in concepts but that is no reason to not include them. I&#39;m sure I would also have said &quot;TEMPLATES? WHY DO WE NEED THIS COMPLEXITY?!!!!&quot;&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;The current C++ standard has been greatly influenced by the various &lt;a href=&quot;http://www.boost.org/&quot; target=&quot;_blank&quot;&gt;Boost&lt;/a&gt; libraries. From lambda to thread, the influence of the Boost development experience is obvious, if not prevalent. Boost made it easy to decide what libraries to include. After all, we&#39;ve had a few years of practical experience with them.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;Reading the list of libraries in &lt;a href=&quot;http://www.boost.org/doc/libs/1_46_1/?sort=boost-version&quot; title=&quot;&quot; target=&quot;_blank&quot;&gt;first-released order&lt;/a&gt;, there are a lot of libraries for various holes in the standard library. The &lt;a href=&quot;http://en.wikipedia.org/wiki/Boost_C%2B%2B_Libraries#Overview&quot; target=&quot;_blank&quot;&gt;Wikipedia article&lt;/a&gt; on the Boost libraries makes it much more clear as to where Boost development has been focused.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;There is another trend: the number of libraries dealing with language issues has steadily decreased over time. Now, that is not to say that there will not be another set of C++0B libraries, there probably will. But I don&#39;t know if it will trigger the same kind of innovation.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;So if that is all true, is C++ over?&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;In the last few years, there has been a gigantic evolution in C++-land: &lt;a href=&quot;http://clang.llvm.org/&quot; target=&quot;_blank&quot;&gt;Clang&lt;/a&gt;. I have been fortunate enough to spend some quality time with Clang in the last little while and I have to say that I have enjoyed it a lot more than the last time I spent some time with another open-source C++ compiler.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;With Clang, it is reasonably easy to add new features, even easier to add features that translate into combinations of existing features.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;So while it was straightforward to add library changes to C++0B due to Boost, it was a lot harder to do the same for language syntax because there was no real experience with many of the proposed features.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;Clang can enable, for the language, what Boost enabled for libraries.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;However, I don&#39;t think Clang is really at the point from an organizational and technical perspective where it can enable and manage the kind of innovation that Boost was able to oversee.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;That being said, I look forward to its role in the future of C++. I think it&#39;s a bright one*.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;* Someone please make C++0B lambda polymorphic.&lt;/p&gt;&lt;br class=&#39;final-break&#39; style=&#39;clear: both&#39; /&gt;</description><link>http://uint32t.blogspot.com/2011/03/c-has-not-jumped-shark.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-1263078223717033205</guid><pubDate>Sun, 15 Aug 2010 18:32:00 +0000</pubDate><atom:updated>2010-08-16T01:13:28.625-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">development</category><category domain="http://www.blogger.com/atom/ns#">emacs</category><category domain="http://www.blogger.com/atom/ns#">testing</category><title>Continuous testing with Emacs</title><description>&lt;p style=&quot;clear: both&quot;&gt;The other day, I came across a very interesting paper on &lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.68.2143&amp;amp;rep=rep1&amp;amp;type=pdf&quot; target=&quot;_blank&quot;&gt;continuous testing during development&lt;/a&gt;. In it, the authors found that program correctness for a group of students could be predicted based on whether the students used continuous or manual testing. Continuous testing is running your compilation and project tests as you save files locally, as opposed to continuous integration which usually works as you check in code. Manual testing is having the student run the test suite manually. Those students who used continuous testing were a few times more likely to finish the project and had less mistakes.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;div&gt;There is nothing in Emacs preventing a developer for implementing this behaviour for their projects so I decided to do that to simplify the edit-test cycle for a particular project.&lt;/div&gt;&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;The key is that after saving a file, using the built-in Emacs hooks, I launch a compile process. The hook only does so if the file being saved is located in the project directory by looking for a string in the filename, &quot;tmp&quot; in this case.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;Here is a &lt;a href=&quot;http://www.screencast.com/users/sohails/folders/Jing/media/2943171e-beaf-49c0-9dc2-4407e54474dc&quot; target=&quot;_blank&quot;&gt;screencast&lt;/a&gt; of the behaviour with the code in the left side of the split. In the right split, I am editing a script (/tmp/runtest) which represents the test suite. The &quot;project&quot; is located in /tmp. The video shows me saving the test suite file twice. Once with no errors and the second time with an error. In the first case, the compilation buffer goes away once the test suite has run, which keeps things tidy. In the second case, the compilation buffer stays around because an error occurred in the &quot;test suite&quot;.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;This specific setup works best with a compilation and test phase which runs relatively fast. To make it work for longer test suites, you&#39;d need to probably modify the test-command code to kill the compilation first. You&#39;d probably also want to modify the after-save-hook to use some kind of timer after which you start the compile.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;There are lots of things which I&#39;d like to work better, but it works OK for me now.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;Let me know how it works out for you if you try it out. The code is &lt;a href=&quot;http://paste.lisp.org/display/113548&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;Enjoy!&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;/p&gt;&lt;br class=&#39;final-break&#39; style=&#39;clear: both&#39; /&gt;</description><link>http://uint32t.blogspot.com/2010/08/continuous-testing-with-emacs.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-9144342528911325769</guid><pubDate>Sat, 22 May 2010 18:22:00 +0000</pubDate><atom:updated>2010-06-27T10:48:31.846-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">research</category><title>Dependency Injection in C++/Plugin-based C++ applications</title><description>&lt;p style=&quot;clear: both&quot;&gt;I have made two of my coding research projects available on bitbucket. One is an example of writing a C++ application which can dynamically load and execute Python plugins and the other is an investigation into a Google Guice inspired dependency injection library in C++.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;See the wikis for some explanation and browse the code. The code is under WTFPL.&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;div&gt;&lt;ul style=&quot;clear: both&quot;&gt;&lt;li&gt;&lt;a href=&quot;http://bitbucket.org/cheez/plugins/wiki/Home&quot; title=&quot;&quot; target=&quot;_blank&quot;&gt;plugins&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://bitbucket.org/cheez/dicpp/wiki/Home&quot; title=&quot;&quot; target=&quot;_blank&quot;&gt;dicpp&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;If you&#39;re wondering, I chose Mercurial because I do not have the brain capacity to understand Git.&lt;/div&gt;&lt;/div&gt;&lt;/p&gt;&lt;p style=&quot;clear: both&quot;&gt;&lt;/p&gt;&lt;br class=&#39;final-break&#39; style=&#39;clear: both&#39; /&gt;</description><link>http://uint32t.blogspot.com/2010/05/dependency-injection-in-cplugin-based-c.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-7012983878207196610</guid><pubDate>Mon, 21 Dec 2009 01:13:00 +0000</pubDate><atom:updated>2009-12-21T11:59:25.796-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">bjam</category><category domain="http://www.blogger.com/atom/ns#">build</category><category domain="http://www.blogger.com/atom/ns#">c++</category><category domain="http://www.blogger.com/atom/ns#">scons</category><title>Using Boost Build on your own projects</title><description>While I am a fan of &lt;a href=&quot;http://www.scons.org/&quot;&gt;SCons&lt;/a&gt;, every now and then I like to dabble in other build systems. One that has intrigued me for some time is &lt;a href=&quot;http://www.boost.org/doc/tools/build/index.html&quot;&gt;Boost Build&lt;/a&gt; (BB). You can visit the linked site to find out more about it but in a nutshell, it is a very elegant way to build C++ software.&lt;br /&gt;&lt;br /&gt;This post will attempt to give you some steps you can use to get started using the tool on your own projects. Note that it is a bit long but if you are new to Boost Jam as I was a few weeks back, I think it might help you get started. Please feel free to ask any clarifying questions in the comments.&lt;br /&gt;&lt;br /&gt;In the following Boost Jam is the build tool and Boost Build is the library on top of the Jam language. I use them interchangeably, and I&#39;m sure people will give me hell for it.&lt;br /&gt;&lt;h2&gt;Building Boost Jam&lt;/h2&gt;&lt;br /&gt;Before getting started, I suggest you build Boost Jam as follows (might as well get Boost too!). I assume you are on a Unix system &lt;s&gt;because there really is no reason to use Windows anymore ;-)&lt;/s&gt; but you should be able to get the same results on Windows with some slight modifications.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;$ wget http://downloads.sourceforge.net/project/boost/boost/1.41.0/boost_1_41_0.tar.bz2&lt;br /&gt;$ tar -xjf boost_1_41_0.tar.bz2&lt;br /&gt;$ pushd boost_1_41_0&lt;br /&gt;$ export BOOST_ROOT=$PWD&lt;br /&gt;$ pushd tools/jam/src/&lt;br /&gt;$ ./build.sh&lt;br /&gt;$ export PATH=$PWD/bin.macosxx86:$PATH # substitute appropriately&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Now, when you type &quot;bjam&quot; at the command prompt, you may get the following output:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;$ bjam&lt;br /&gt;warning: No toolsets are configured.&lt;br /&gt;warning: Configuring default toolset &quot;gcc&quot;.&lt;br /&gt;warning: If the default is wrong, your build may not work correctly.&lt;br /&gt;warning: Use the &quot;toolset=xxxxx&quot; option to override our guess.&lt;br /&gt;warning: For more configuration options, please consult&lt;br /&gt;warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html&lt;br /&gt;&lt;br /&gt;error: error: no Jamfile in current directory found, and no target references specified.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;h2&gt;The Jam Language&lt;/h2&gt;&lt;br /&gt;One complaint about Boost Build is that we must use the Jam language. However, it&#39;s really not so bad. While I would prefer Python, the Jam language is consistent and very simple. The main things to remember (this is my mental model and may not be technically accurate):&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;Rules are the same as functions in other languages&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Parameters to functions are separated by &quot;:&quot;&lt;/li&gt;&lt;br /&gt; &lt;li&gt;All tokens are white space separated (use quotes to embed white space)&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Results of functions can be used by enclosing the function call in a [] pair&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Comments start with # and go to the end of the line&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Here is an extremely simple example of a rule/function (create a file called &quot;Jamroot&quot; in the current directory and put in the following):&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;rule show-list ( list-of-stuff + : sep ) #1&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for local l in $(list-of-stuff) #2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo $(l) $(sep) ; #3&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return &quot;Hello, World&quot; ;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;echo [ show-list 1 2 3 : &quot;|&quot; ] ; #4&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;This line declares a new rule called &quot;show-list&quot; which accepts two parameters: a list as the first parameter and a single value as the second. Note the &quot;+&quot; modifier on the first parameter. This indicates to the build tool that at least one parameter is expected. You can use &quot;*&quot; to indicate 0 or more. I believe this can also be used to indicate optional parameters &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;This line is a for loop using a local variable. Note the variable expansion using the &quot;$()&quot; syntax. In this case, each iteration of the loop will expand to an element of the list in list-of-stuff.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Here we call the echo rule. Note that the line is terminated by the &quot;;&quot; symbol. This is required!&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Finally, we call the new rule with a list as the first parameter and a keyword enclosed in quotes as the second parameter. We use the result of that rule and pass it to echo.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;If you execute &quot;bjam&quot;, the output looks something like:&lt;br /&gt;&lt;verbatim&gt;&lt;br /&gt;1 |&lt;br /&gt;2 |&lt;br /&gt;3 |&lt;br /&gt;Hello, World&lt;br /&gt;&lt;/verbatim&gt;&lt;br /&gt;Pretty boring!&lt;br /&gt;&lt;h2&gt;Creating a new project&lt;/h2&gt;&lt;br /&gt;When Boost Jam is invoked, it looks for a file called &quot;Jamroot&quot; in the current directory or in one of the parents of the current directory. This is where you define project global settings. Let&#39;s do that now. Create a new file called Jamroot and include the following contents:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;import toolset ;&lt;br /&gt;&lt;br /&gt;project app&lt;br /&gt;&amp;nbsp;&amp;nbsp;: requirements&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;threading&amp;gt;multi&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;link&amp;gt;static&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;warnings&amp;gt;all&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;warnings-as-errors&amp;gt;on&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;# Equivalent to &amp;lt;toolset&amp;gt;darwin: &amp;lt;architecture&amp;gt;x86 &amp;lt;toolset&amp;gt;darwin: &amp;lt;address-model&amp;gt;32&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[ conditional &amp;lt;toolset&amp;gt;darwin: &amp;lt;architecture&amp;gt;x86 &amp;lt;address-model&amp;gt;32 ]&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;: default-build debug release&lt;br /&gt;&amp;nbsp;&amp;nbsp;: build-dir build&lt;br /&gt; ;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The requirements state that all artifacts should be built using multi-threaded libraries, built statically with all warnings and all errors. Additionally, on darwin, we only want to build 32-bit executables for the x86 architecture.&lt;br /&gt;&lt;br /&gt;In the default build (when you type just bjam), both debug and release variants will be built and put into the build directory relative to the Jamroot.&lt;br /&gt;&lt;br /&gt;Now, type &quot;bjam&quot;. If you are on OSX, you may see something like the following:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;$ bjam&lt;br /&gt;warning: No toolsets are configured.&lt;br /&gt;warning: Configuring default toolset &quot;gcc&quot;.&lt;br /&gt;warning: If the default is wrong, your build may not work correctly.&lt;br /&gt;warning: Use the &quot;toolset=xxxxx&quot; option to override our guess.&lt;br /&gt;warning: For more configuration options, please consult&lt;br /&gt;warning: http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html&lt;br /&gt;...found 1 target...&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The reason for this is that BB guesses the toolset but on OSX we should  really be using the darwin toolset. When Boost Jam starts up, it looks at ~/user-config.jam (somewhere similar on Windows) for a user configuration file. Add one with the following contents:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;# ~/user-config.jam&lt;br /&gt;using darwin ;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Now when you hit bjam, you should see something like:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;$ bjam&lt;br /&gt;...found 1 target...&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Alternatively, if you don&#39;t want to pollute your file system, you can execute:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;$ bjam toolset=darwin&lt;br /&gt;...found 1 target...&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;h2&gt;Adding a project target&lt;/h2&gt;&lt;br /&gt;Now we will add a simple executable that links to some Boost libraries. Create a directory named &quot;app&quot; in your current directory and create a file in this directory named &quot;Jamfile&quot; with the following contents:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;# app/Jamfile&lt;br /&gt;exe app : [ glob *.cpp ] ;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Additionally, create a C++ file in the app directory with a trivial main function and the &quot;.cpp&quot; extension. Execute bjam. Nothing changed! That&#39;s because we haven&#39;t asked BJam to build our project. Try executing &quot;bjam app&quot;. You should see something like the following:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;$ bjam toolset=darwin app&lt;br /&gt;...found 20 targets...&lt;br /&gt;...updating 17 targets...&lt;br /&gt;common.mkdir build&lt;br /&gt;common.mkdir build/app&lt;br /&gt;common.mkdir build/app/darwin-4.0.1&lt;br /&gt;....&lt;br /&gt;darwin.compile.c++ build/app/darwin-4.0.1/debug/address-model-32/architecture-x86/link-static/threading-multi/main.o&lt;br /&gt;darwin.link build/app/darwin-4.0.1/debug/address-model-32/architecture-x86/link-static/threading-multi/app&lt;br /&gt;common.mkdir build/app/darwin-4.0.1/release&lt;br /&gt;...&lt;br /&gt;darwin.compile.c++ build/app/darwin-4.0.1/release/address-model-32/architecture-x86/link-static/threading-multi/main.o&lt;br /&gt;darwin.link build/app/darwin-4.0.1/release/address-model-32/architecture-x86/link-static/threading-multi/app&lt;br /&gt;...updated 17 targets...&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Note that both debug and release builds were created with one invocation. To restrict to one or the other, execute &quot;bjam variant=debug&quot; or &quot;bjam variant=release&quot;.&lt;br /&gt;&lt;h2&gt;Using Boost&lt;/h2&gt;&lt;br /&gt;Remember when we downloaded Boost? Now we will use it! The mechanism for using another Boost Jam project is the &quot;use-project&quot; rule. Add the following to your Jamroot file:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;use-project /boost : ../boost_1_41_0 ;&lt;br /&gt;alias boost_thread&lt;br /&gt;&amp;nbsp;&amp;nbsp;: /boost/thread//boost_thread&lt;br /&gt;&amp;nbsp;&amp;nbsp;: &amp;lt;warnings-as-errors&amp;gt;&gt;off # bunch of warnings&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Here we told the build system where the project with the id &quot;/boost&quot; is located. In this case, it is ../boost_1_41_0, relative to the Jamroot file. Yours might be different. Additionally, we added an alias for the Boost thread library. The main reason for this is that a single alias reduces proliferation of any special handling needed.&lt;br /&gt;&lt;br /&gt;If you type &quot;bjam&quot; now, you will not be surprised that nothing is being built. Let&#39;s fix that now. Add the following to the Jamroot file:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;build-project app ;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Now, whenever you invoke bjam, the app project will always be built. Invoke bjam now. You should notice that Boost thread is not being built. Again, this is not surprising. We aren&#39;t using it anywhere! Modify app/Jamfile to look like the following and execute bjam:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;exe app : [ glob *.cpp ] ..//boost_thread ;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;You will notice that Boost thread is being built in the Boost directory. This is not very useful as build artifacts are spread all over your disk. (Un?)Fortunately, there is a hack to making this work. Create a new file at the level of your Jamroot named &quot;boost-build.jam&quot;. Fill it with the following contents:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;# Add --build-dir to command line so that boost Jamfiles pick it up and use this directory to build.&lt;br /&gt;&lt;br /&gt;ARGV += --build-dir=build ;&lt;br /&gt;&lt;br /&gt;BOOST_ROOT = vendor/boost ;&lt;br /&gt;BOOST_BUILD = $(BOOST_ROOT)/tools/build/v2 ;&lt;br /&gt;boost-build $(BOOST_BUILD) ;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Boost Build looks for this file when building Boost (I think) so here we add the --build-dir parameter so that when building boost, it will build to our build directory. That&#39;s a lotta building ;-)&lt;br /&gt;&lt;br /&gt;Hit &quot;bjam&quot; now. You should see Boost thread being built statically in the build directory now, in both debug and release variants.&lt;br /&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;In this post, you learned how to build Boost Jam, a little bit about the Jam language and created a simple project utilizing the Boost libraries. Next time, I will build on this post to cover making a plugin-aware C++ application (this is really quite exciting for me!) Again, if you have any question or comments, feel free to leave them below.</description><link>http://uint32t.blogspot.com/2009/12/using-boost-build-on-your-own-projects.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>4</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-8456335778331917180</guid><pubDate>Sun, 29 Nov 2009 20:37:00 +0000</pubDate><atom:updated>2009-11-29T16:27:27.767-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">30day</category><category domain="http://www.blogger.com/atom/ns#">notaloser</category><category domain="http://www.blogger.com/atom/ns#">quit</category><category domain="http://www.blogger.com/atom/ns#">soapbox</category><category domain="http://www.blogger.com/atom/ns#">software</category><title>Knowing when to quit</title><description>&quot;Crossing the Chasm&quot; and &quot;The Dip&quot; are both great books which talk about a distinguishable lag between when early adopters and the bulk of your target market start paying attention to you, financially anyway.&lt;br /&gt;&lt;br /&gt;There is a problem though: a failure and such a chasm look exactly the same for a fairly long time.&lt;br /&gt;&lt;br /&gt;I think a second problem which I&#39;m not sure any book really addresses is that some think they are in a dip when in fact they never entered a dip to begin with. That is why you hear things like &quot;You can&#39;t give up now, you made $200!&quot; because they assume that every market is infinitely sized and you&#39;ve just got to keep going!&lt;br /&gt;&lt;br /&gt;I read somewhere that the average annual sales for shareware is $400. Enough of those and the payment processor is doing alright but of course the authors are not. Classic case of middle-man makes the most money in a transaction.&lt;br /&gt;&lt;br /&gt;So if you are one of those $400/year authors and you need to spend more than 2 hours a year on maintenance, I would really think that is a good reason to quit and do something else. You&#39;re not going to miss the $400. &lt;span style=&quot;font-weight: bold;&quot;&gt;You never entered a dip.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There is a very popular and  article titled &lt;a href=&quot;http://www.gamedev.net/reference/articles/article1950.asp&quot;&gt;Shareware Amateurs vs Shareware Professionals&lt;/a&gt;. I highly recommend a read. Almost as a case-in-point, the author of that article has quit software altogether and is a fairly successful blogger. That is knowing when to quit.&lt;br /&gt;&lt;br /&gt;If you have to quit, which I do advocate in the right circumstances, it does not mean you are giving up. You are just going to keep trying until you hit your mark. And for heaven&#39;s sake, don&#39;t think of yourself as a failure. A failure is someone who never tries.&lt;br /&gt;&lt;br /&gt;What do you think?</description><link>http://uint32t.blogspot.com/2009/11/knowing-when-to-quit.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-1037310819205501139</guid><pubDate>Sat, 17 Oct 2009 14:09:00 +0000</pubDate><atom:updated>2009-10-17T11:24:24.991-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">qt</category><title>Using Boost Function with Qt, Part 2.</title><description>[Following up &lt;a href=&quot;http://uint32t.blogspot.com/2008/11/using-boost-bind-and-boost-function.html&quot;&gt;this post&lt;/a&gt;]&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://uint32t.blogspot.com/2008/11/using-boost-bind-and-boost-function.html?showComment=1255764339129#c1759598075976409702&quot;&gt;Johan asks&lt;/a&gt;:&lt;br /&gt;&lt;dl class=&quot;avatar-comment-indent&quot; id=&quot;comments-block&quot;&gt;&lt;dd class=&quot;comment-body&quot;&gt;&lt;p&gt;please, please post that follow-up. I&#39;m new to Qt and have just run into this problem. While searching the net, I think your solution seems like the best approach!&lt;br /&gt;&lt;/p&gt;&lt;/dd&gt;&lt;/dl&gt;Who am I to deny a seeker of knowledge? Having used this method in a couple of projects now, I think it is fairly sound and easy to maintain. So here goes.&lt;br /&gt;The main problem with the solution outlined in the earlier post was that it could not handle multiple arguments. On that same post, Ken posted &lt;a href=&quot;http://paste.lisp.org/display/87422&quot;&gt;his solution&lt;/a&gt; apparently inspired by mine. His solution also handles multiple arguments but does it by implementing qt_metacall, i.e., mimicking moc. This is probably the most scalable solution and I&#39;ll probably give it a second look when I need to do this again. The only problem might be requiring exact matches for types but I am not sure how much of an issue this is for code I have written.&lt;br /&gt;&lt;br /&gt;To review, the problem is that we want to use function objects (Boost Bind, Boost Function, etc) as Qt slots because sometimes it is too much work to create stateful slots.&lt;br /&gt;&lt;br /&gt;My solution looked something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;struct SignalHandler0 : QObject&lt;br /&gt;{&lt;br /&gt;private:&lt;br /&gt;Q_OBJECT&lt;br /&gt;public:&lt;br /&gt;SignalHandler0(QObject * parent,&lt;br /&gt;              boost::function&lt;void(void)&gt; const &amp;amp; f):&lt;br /&gt; QObject(parent), // parent will delete this object when destructed&lt;br /&gt; m_f(f) {}&lt;br /&gt;&lt;br /&gt;public slots:&lt;br /&gt;void&lt;br /&gt;handleSignal()&lt;br /&gt;{&lt;br /&gt; try&lt;br /&gt; {&lt;br /&gt;   m_f();&lt;br /&gt; }&lt;br /&gt; catch(...)&lt;br /&gt; {&lt;br /&gt;   // Cannot throw exceptions from signals.&lt;br /&gt;   ASSERT_BUG_HERE&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;private:&lt;br /&gt;boost::function&lt;void()&gt;&lt;void(void)&gt; m_f;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;bool&lt;br /&gt;connect(QObject * sender, const char * signal,&lt;br /&gt;     boost::function&lt;void(void)&gt;&lt;void()&gt; const &amp;amp; f)&lt;br /&gt;{&lt;br /&gt;return QObject::connect(sender,signal,&lt;br /&gt;                       // Note: Not a leak as sender will delete the handler when destructed&lt;br /&gt;                       new SignalHandler0(sender,f),SLOT(handleSignal()));&lt;br /&gt;}&lt;br /&gt;&lt;/void()&gt;&lt;/void(void)&gt;&lt;/void(void)&gt;&lt;/void()&gt;&lt;/void(void)&gt;&lt;/pre&gt;To extend it to a single argument, we might do:&lt;br /&gt;&lt;pre&gt;struct SignalHandler1 : QObject&lt;br /&gt;{&lt;br /&gt;private:&lt;br /&gt;Q_OBJECT&lt;br /&gt;public:&lt;br /&gt;SignalHandler1(QObject * parent,&lt;br /&gt;              boost::function&lt;void(a)&gt;&lt;void(qstring&gt; const &amp;amp; f):&lt;br /&gt; QObject(parent), // parent will delete this object when destructed&lt;br /&gt; m_f(f) {}&lt;br /&gt;&lt;br /&gt;public slots:&lt;br /&gt;void&lt;br /&gt;handleSignal(QString const &amp;amp; a)&lt;br /&gt;{&lt;br /&gt; try&lt;br /&gt; {&lt;br /&gt;   m_f(a);&lt;br /&gt; }&lt;br /&gt; catch(...)&lt;br /&gt; {&lt;br /&gt;   // Cannot throw exceptions from signals.&lt;br /&gt;   ASSERT_BUG_HERE&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;private:&lt;br /&gt;boost::function&lt;void(a)&gt;&lt;void(qstring&gt; m_f;&lt;br /&gt;};&lt;br /&gt;&lt;/void(qstring&gt;&lt;/void(a)&gt;&lt;/void(qstring&gt;&lt;/void(a)&gt;&lt;/pre&gt;&lt;br /&gt;That is, create a new class with the right signature. So you might think: well that screams for class templates! Unfortunately, Qt does not support class templates. Doh.&lt;br /&gt;&lt;br /&gt;So basically, we write it out:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;struct SignalHandler : public QObject&lt;br /&gt;{&lt;br /&gt;template&lt;typename&gt;&lt;typename signature=&quot;&quot;&gt;&lt;br /&gt;SignalHandler(QObject * parent,boost::function&lt;signature&gt;&lt;signature&gt; f):&lt;br /&gt; QObject(parent),&lt;br /&gt; m_handler(new SignalHandlerImpl&lt;signature&gt;(f))&lt;br /&gt;{}&lt;br /&gt;&lt;br /&gt;struct SignalHandlerBase&lt;br /&gt;{&lt;br /&gt; virtual ~SignalHandlerBase();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;template &lt;typename&gt;&lt;typename signature=&quot;&quot;&gt;&lt;br /&gt;struct SignalHandlerImpl&lt;br /&gt;{&lt;br /&gt; SignalHandlerImpl(boost::function&lt;signature&gt;&lt;signature&gt; f):m_f(f){}&lt;br /&gt; boost::function&lt;signature&gt;&lt;signature&gt; f;&lt;br /&gt;}&lt;br /&gt;public slots:&lt;br /&gt;void handleSignal(void);&lt;br /&gt;void handleSignal(QString const &amp;amp;);&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;private:&lt;br /&gt;shared_ptr&lt;signalhandlerbase&gt; m_handler;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;void&lt;br /&gt;SignalHandler::handleSignal(void)&lt;br /&gt;{&lt;br /&gt;typename SignalHandlerImpl&lt;void(void)&gt; type;&lt;br /&gt;type* handler = dynamic_cast&lt;type*&gt;;(m_handler.get());&lt;br /&gt;ASSERT(handler);&lt;br /&gt;handler-&gt;f();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void&lt;br /&gt;SignalHandler::handleSignal(QString const &amp;amp; a)&lt;br /&gt;{&lt;br /&gt;typename SignalHandlerImpl&lt;void(qstring&gt; type;&lt;br /&gt;type* handler = dynamic_cast&lt;type*&gt;(m_handler.get());&lt;br /&gt;ASSERT(handler);&lt;br /&gt;handler-&gt;f(a);&lt;br /&gt;}&lt;br /&gt;&lt;/type*&gt;&lt;/void(qstring&gt;&lt;/type*&gt;&lt;/void(void)&gt;&lt;/signalhandlerbase&gt;&lt;/signature&gt;&lt;/signature&gt;&lt;span style=&quot;font-family:Georgia,serif;&quot;&gt;&lt;br /&gt;You can use macros to generate these handlers. You will also need overloaded connect() functions:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;template&lt;typename signature=&quot;&quot;&gt;&lt;typename&gt;&lt;br /&gt;QObject*&lt;br /&gt;connect(QObject * sender,&lt;br /&gt;     const char * signal,&lt;br /&gt;     boost::function&lt;signature&gt;&lt;signature&gt; slot);&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;template&lt;&gt;&lt;br /&gt;QObject*&lt;br /&gt;connect&lt;void(void)&gt;&lt;void(void)&gt;(QObject * sender,&lt;br /&gt;                  const char * signal,&lt;br /&gt;                  boost::function&lt;void(void)&gt;&lt;void(void)&gt; slot);&lt;br /&gt;&lt;br /&gt;template&lt;&gt;&lt;br /&gt;QObject*&lt;br /&gt;connect&lt;void(qstring&gt;&lt;void(qstring&gt;(QObject * sender,&lt;br /&gt;                            const char * signal,&lt;br /&gt;                            boost::function&lt;void(qstring&gt;&lt;void(qstring&gt; slot);&lt;br /&gt;&lt;/void(qstring&gt;&lt;/void(qstring&gt;&lt;/void(qstring&gt;&lt;/void(qstring&gt;&lt;/void(void)&gt;&lt;/void(void)&gt;&lt;/void(void)&gt;&lt;/void(void)&gt;&lt;/signature&gt;&lt;/signature&gt;&lt;/typename&gt;&lt;/typename&gt;&lt;/signature&gt;&lt;/signature&gt;&lt;/typename&gt;&lt;/typename&gt;&lt;/signature&gt;&lt;/signature&gt;&lt;/signature&gt;&lt;/typename&gt;&lt;/typename&gt;&lt;/pre&gt;Again, you can use macros.&lt;br /&gt;&lt;br /&gt;I prefer Ken&#39;s solution from a technical standpoint. It is a good evolution. The main advantage of his solution is that the amount of code you need to add scales linearly with the number of arguments you need to handle whereas with my solution, they scale with the number of signals and that there are no macros.&lt;br /&gt;&lt;br /&gt;The main advantage of my solution is that it is simpler to understand and maintain, which might be worth the extra code.&lt;br /&gt;&lt;br /&gt;Hope that helps!</description><link>http://uint32t.blogspot.com/2009/10/using-boost-function-with-qt-part-2.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-3503919203351431488</guid><pubDate>Wed, 19 Aug 2009 05:04:00 +0000</pubDate><atom:updated>2009-08-19T01:17:29.119-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">money</category><title>The best market is one with lots of money</title><description>There are always people who feel that developing plug-ins is not a profitable market. Now while developing a plug-in may not make you as rich as Bill Gates, if there is a sizable market, you will make money.&lt;br /&gt;&lt;br /&gt;So if you are looking for whether your idea makes sense, here is a simple relation to figure it out:&lt;br /&gt;&lt;br /&gt;UnitPrice * NumberOfQualifiedCustomers * ConversionRate &gt;= SomeSpecificFinancialGoal&lt;br /&gt;&lt;br /&gt;If the statement is true, you will make money. If it is not, you will fail.&lt;br /&gt;&lt;br /&gt;I&#39;m pretty sure that I grossly over estimated NumberOfQualifiedCustomers when creating &lt;a href=&quot;http://worklogassistant.com&quot;&gt;Worklog Assistant&lt;/a&gt;. How did I over calculate? Simply, the number of total JIRA users who also use JIRA as a timesheet system is quite small (yeah, duh right?) I would not have known this if I did not reach market quickly.&lt;br /&gt;&lt;br /&gt;However, I used very pessimistic values for ConversionRate so maybe that balanced it out because I still reached my financial goals.&lt;br /&gt;&lt;br /&gt;What does this mean for me? It means V2 is going to kick some serious ass. Oh how I wish I could have people to work on this with me, wink wink :-)</description><link>http://uint32t.blogspot.com/2009/08/best-market-is-one-with-lots-of-money.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-8779086434072392022</guid><pubDate>Thu, 09 Jul 2009 21:12:00 +0000</pubDate><atom:updated>2009-07-22T01:39:34.706-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">afk</category><category domain="http://www.blogger.com/atom/ns#">bzr</category><category domain="http://www.blogger.com/atom/ns#">dontreadme</category><category domain="http://www.blogger.com/atom/ns#">futurereference</category><title>Going AFK with Bazaar</title><description>One thing I&#39;ve really liked about distributed VC systems is that they handle merging really well. Of course, this is not limited to DVCSs. Subversion and Perforce have very good merging but do not support offline work very well.&lt;br /&gt;&lt;br /&gt;I&#39;ve been using Bazaar for a little while now for &lt;a href=&quot;http://worklogassistant.com/&quot;&gt;my app&lt;/a&gt; because I knew that I would need to be offline every now and then. I just had one of those periods and thought it would be a great chance to see how well AFK mode works with Bazaar.&lt;br /&gt;&lt;br /&gt;This is more for my own future reference rather than for you :-)&lt;br /&gt;&lt;br /&gt;laptop $ rsync -avz -e ssh sohail@desktop:/home/sohail/bzr/ ~/bzr&lt;br /&gt;laptop $ bzr branch ~/bzr/code/master project&lt;br /&gt;laptop $ bzr bind ~/bzr/code/master&lt;br /&gt;&lt;br /&gt;Now I can work offline in the &quot;project&quot; directory and all checkins go to ~/bzr .&lt;br /&gt;&lt;br /&gt;Upon return:&lt;br /&gt;&lt;br /&gt;laptop $ rsync -avz -e ssh ~/bzr/ sohail@desktop:/home/sohail/bzr&lt;br /&gt;&lt;br /&gt;NOTE TRAILING SLASH ON SOURCE DIRECTORY!!!!!1111oneone....&lt;br /&gt;&lt;br /&gt;Note: I think the above is insane. Ideally, I&#39;d just do something like:&lt;br /&gt;&lt;br /&gt;laptop $ bzr checkout bzr+ssh://sohail@desktop/home/sohail/bzr bzr&lt;br /&gt;laptop $ cd bzr&lt;br /&gt;laptop $ bzr work-offline&lt;br /&gt;&lt;br /&gt;Return from afk:&lt;br /&gt;&lt;br /&gt;laptop $ bzr I&#39;m back&lt;br /&gt;&lt;br /&gt;Or something like that.</description><link>http://uint32t.blogspot.com/2009/07/going-afk-with-bazaar.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4168503339888369834.post-1161318549264845423</guid><pubDate>Mon, 08 Jun 2009 23:37:00 +0000</pubDate><atom:updated>2009-06-08T19:40:29.128-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">vancpp</category><title>VanCPP June meeting</title><description>If you are in Vancouver and interested in programming (who isn&#39;t?!) you might want to make your way to the VanCPP meeting in June. The announcement is below:&lt;br /&gt;      &lt;!--~-|**|PrettyHtmlEnd|**|-~--&gt;       &lt;p&gt;Our June 2009 meeting will be held on Thursday, June 18. Please note the &lt;a href=&quot;http://workspacecafe.ca/&quot;&gt;new venue&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Topic: &lt;span style=&quot;color:#407f00;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;Concurrent Programming in the D Programming Language&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Presented by &lt;strong&gt;Walter Bright&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;b&gt;Abstract&lt;/b&gt;: Many-core concurrent programming offers exciting and compelling advantages. The single core, single thread programming model is assumed by imperative programming languages. This model offers sequential consistency as its fundamental characteristic.&lt;wbr&gt;Because many-core systems use layered cache memory systems,sequential consistency is not guaranteed among threads.Because imperative programming languages allow implicit sharing of data between threads, many misguided idioms and optimizations are possible that erroneously assume sequential consistency.&lt;wbr&gt;One example of this is the double checked locking optimization.&lt;wbr&gt;The pernicious nature of these sorts of bugs is they defy programmers&#39; natural intuition about how programs behave,they are not statically detectable, and there is no way to reliably test a program to rule out the existence of such bugs.A program may appear to work, but have problems appear years later, fail when ported to a different platform, and such problems may be extremely hard to reproduce and track down.In essence, the correctness of the program relies entirely on the expertise and care of the programmer.This is not an acceptable situation for developers of programs that require high reliability.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;The &lt;a href=&quot;http://www.digitalmars.com/d/&quot;&gt;D programming language&lt;/a&gt; is an imperative programming language with an innovative type system that prevents implicit sharing and also fosters a complete, integrated pure functional subset. It is possible to statically verify that D programs do not have sequential consistency bugs. The double checked locking optimization bug is not possible. Type support for shared data and immutable data, as well as pure functions, means that mutating data interactions between threads can occur only under carefully controlled conditions.This dramatically reduces the problem space for concurrency bugs from the whole of the source code to a small subset of it, making it a much more tractable problem.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;Speaker bio:&lt;/strong&gt; &lt;a href=&quot;http://www.walterbright.com/&quot;&gt;Walter Bright&lt;/a&gt; graduated from Caltech in 1979 with a degree in mechanical engineering. He worked for Boeing for three years on the development of the 757 stabilizer trim system. He then switched to writing software, in particular compilers, and has been writing them ever since.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;The meeting will be held at:&lt;br /&gt;&lt;strong&gt;&lt;a href=&quot;http://workspacecafe.ca/&quot;&gt;Workspace&lt;/a&gt;&lt;/strong&gt;&lt;br /&gt;&lt;a href=&quot;http://maps.google.com/maps?f=q&amp;amp;source=s_q&amp;amp;hl=en&amp;amp;geocode=&amp;amp;q=21+water+street,+vancouver,+canada&amp;amp;ie=UTF8&amp;amp;z=16&amp;amp;iwloc=A&quot;&gt;21 Water Street&lt;/a&gt;&lt;br /&gt;Vancouver, BC&lt;br /&gt;V6B 1A&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Regards,&lt;/p&gt;&lt;p&gt;Vladan Vidakovic&lt;/p&gt;</description><link>http://uint32t.blogspot.com/2009/06/vancpp-june-meeting.html</link><author>noreply@blogger.com (Unknown)</author><thr:total>0</thr:total></item></channel></rss>