M-A's

technology blog

Friday 9 October 2009

Windows, just another dumb terminal?

The more I use ssh + screen, the more I realize Windows is an excellent dumb terminal mainly due to its support of awkward monitor setup support. This is four monitors, 1280, 1920 in portrait, 1920 in portrait, 1920 in landscape.

Update: Note that Windows' 7 WinKey-Arrow and WinKey-Shift-Arrow shortcut makes it even better as a dumb terminal.

Monday 28 September 2009

Linker

Do you know what you are linking?
I'm surprised on how many people are confused about the linking process in general. This discussion will focus on MSVC in particular but this discussion stands for the gnu toolset too. First let's define:
  • A compile unit as a single C++ (.cc) source file generating a single object (.obj) file.
  • A PE is a single output unit from the linker.
  • A symbol is a single named component globally visible, like a global function, class definition, member function, global variable, imported symbol with dllimport or template instance; this list is obviously not exhaustive.
Compilation units
When linking, all inputs are linked together to extracts symbols and put them in the output file. This is important for the linker to have compilation units be easy to differentiate one to each other. The reason is that the compilation unit's name (the source file name) is used in the symbol mangling, especially for file static global variable. This is also important since often even if the source files are in various subdirectories, the output objects are in a single intermediary directory. This can cause problems when you have 2 sources files with the same name. For example, libjingle, up to revision 7, has 2 compile units with the same name: constants.cc and constants.cc. If both arrive in the same output dir, you're in trouble. But how come it works in this specific case? Well, when the developer adds the second file in the Visual Studio IDE, the IDE will automatically set the ObjectFile attribute to to add a '1' postfix. See libjingle.vcproj.

PE and incremental linking
Every output PE must have a unique name in a solution. This is something we are hitting in the Chromium project since we have chrome.exe and chrome.dll. The issue we face is that both generate chrome.ilk for incremental linking. This cause that incremntal linking fails every time. The workaround is to output one of the binaries in the intermediary output directory and hardlink it back at the right place. Lame but works.

Every symbol is not on equal footing
When defining the same symbol multiple times into a PE, the linker will give errors on multiple defined symbols. To alleviate this problem, you can define the symbol as selectany, e.g. a weak symbol. But if the two symbol definitions are not exactly the same, you can get into real trouble since one is selected at random at link time.

The interesting twist comes with static libraries. If a symbol is defined in one or multiple static libraries and in an object file, the symbol defined in the object file will be used. The best commonly used example is DllMain. When creating a DLL, if it is defined in a .obj file, your definition will be used. If not defined in an object file, the definition provided in the CRT static library will be used.
So in short, the linker has different priorities when linking its inputs: static libraries are second class citizens to object files.
So if a symbol defined in a static library is not referenced by a symbol in a object file, it will not be linked in. That's why many people will use the /INCLUDE parameter to force a symbol from a static library to be included. ATL is one doing that with "#pragma comment(linker, "/include:_forceAtlDllManifest")" in atlbase.h.

Scalability issue
But linking large static libraries takes time. For the Chromium project, some of our libraries are significantly large, browser.lib and webcore.lib being respectively 320 and 408 megs as revision 27335. One way to help speed up is to use Use Library Dependency Inputs. This permits skipping over the static library linking step. Why? Since static libraries cannot use incremental linking, they are much slower to link in debug than actual PE.

But all the rules described above change with Use Library Dependency Inputs since the final linker step links only object files and no static libraries. You see it coming, every symbols are now on equal footing. Which mean a lot of fun and helps find a lot of problems.

I saw unit tests including another compile unit. That results in duplicate symbols. I saw another project having 2 different main() functions. Same failure. I saw an installer including unit tests. Same failure. Why does that work without the ULDI flag? Because of different symbol priority between object file and static library. When a symbol exists in an object file, the symbols defined in static libraries are silently discarded. If all the symbols defined in static libraries are now on higher priority, that breaks on every symbols that are ambiguous.

That concludes my short explanation.

Tuesday 22 September 2009

usb key windows install

These days I install Windows 7 often but I can't help to remember the steps from Vista:

Open an elevated command prompt:
diskpart
list disk
select disk 2   <- choose usb key!
clean
create partition primary
select partition 1
active
format fs=fat32 quick
assign
exit
xcopy /h /e /q path\to\uncompressed\iso e:\   <- choose usb key!
All this can be done through GUI with Computer Management / Disk Management. Choose an open source program in http://en.wikipedia.org/wiki/List_of_ISO_image_software for the iso extraction.

Thursday 27 August 2009

git notes

This message is for me only. I don't not expect you learn anything from this or even think this is useful. This post represents a huge amount of fighting with blogspot editor.

WORN: git is similar to perl: write-once, read-never.

CONFIGURATION
  • git config --global color.ui auto (1.6+)
  • git config --global user.email me@me.com
  • git config --global user.name "Mini Me"
  • git config --global alias.st status
  • git config --global alias.br branch
  • Basically everything at http://git.wiki.kernel.org/index.php/Aliases#Shortcuts 
  • echo *.pyc>>.git/info/exclude
  • Edit these two in your ~/.gitconfig
    • [alias] 
    •   ignored = "!cd \"$(git rev-parse --show-cdup)\" && git clean -n -d | cut -c 14- | sed -e \"s/\\/$//\""
    •   ignoreall = "!cd \"$(git rev-parse --show-cdup)\" && git clean -n -d | cut -c 14- | sed -e \"s/\\/$//\" >> .git/info/exclude"
  • Use git-prompt! I use:
    • max_file_list_length=30
    • default_user=me
    • default_host=myhost
    • default_domain=mydomain
    • cwd_cmd='cwd_truncate 30'
    • and enable only the VCS I use.
  • Use git-completion.bash!
MODIFICATIONS

  • git remote add origin2 user@host:path/to/repo.git
  • git pull --rebase remote_name remote_branch
  • git svn clone svn://host/repo --stdlayout
  • git svn clone svn://host/repo -T sub/directory
    • You may want to use --prefix=origin/ but I like to just type "trunk" instead of "origin/trunk"
  • git svn rebase 
  • git push remote_name remote_branch 
    • remote_name and remote_branch are optional if branch.merge is set
  • git merge --squash --no-commit [other branch]
  • git mergetool --tool=kdiff3
    • when vimdiff is unsufficient and I'm on X
  • git cherry-pick (hash)
    • from the branch where you want to include your change
  • git checkout -b new_branch trunk
  • git checkout another_branch file_to_bring_here
    • another branch can be HEAD~1 for a past revision
    • note the file is implicitly "added" so git diff will not display anything, use git diff HEAD
  • git revert (hash)
  • git add .
  • git add -p
    • To index only some parts (hunks), useful to discard some changes by following with a commit and reset.
  • git reset "file"
    • Really the reverse of git add "file"
  • git commit -a -m "bleh"
  • git commit --amend
    • Modify the last commit
  • git branch -D branch_to_delete
  • git push origin :branch_to_delete
  • git reflog
    • To find a deleted branch back
  • git checkout -b new_branch HEAD@{1}
    • To revive it
  • git rebase -i default~2^
    • To squash or amend previous commits, reappend to previous head. Warning, rewrites history! ^ means rewrite on the parent 
  • git rebase --continue
    • Never rebase after pushing something!! Only merge!

QUERIES

  • git branch -a -v
  • git diff old..new
    • Every commit you can reach by new not reachable by new
  • git diff master...HEAD
    • reachable by either but not both, XOR
  • git diff master...
    • HEAD is implicit
  • git diff `git merge-base HEAD master`
    • refer to 3 commits before
  • git diff HEAD~3
  • git diff HEAD^^^
  • git diff HEAD^2
    • alternate parent
  • git diff master~2^2
    • headache, really
  • git log HEAD ^trunk
    • when trunk was updated, awesome
  • git log -p HEAD ^git-svn
    • full diff per log
  • git log --pretty=oneline
  • git log --pretty=format:"%h %an %ar - %s"
  • git log --pretty=format:"%h %an %ar - %s" --graph
  • git status
  • git clean -d -n -x
    • list currently ignored files
  • git blame -C1 file
    • search for renames
  • git diff --merge
    • for 3-way merge conflict
  • git show (hash)
    • will show how a merge conflict was fixed

Then read http://www.kernel.org/pub/software/scm/git/docs/user-manual.html

screen notes

This message is for me only. I don't not expect you learn anything from this or even think this is useful.
C-a means Ctrl-a

Key         | Action           | Notes
C+a c       | new window       |
C+a n       | next window      | I bind F12 to this
C+a p       | previous window  | I bind F11 to this
C+a N       | go to window N   |
C+a "       | window list      | window list is in status line
C+a C+a     | previous window  |
C-a ?       | help             | unbound commands only
C+a :       | screen cmd prompt| up shows last commands
C+a Esc / [ | scrllbck/cpy mode| Enter start and end region
C+a ]       | paste buffer     | Supports pasting between windows
C-U / D     | page up/down     | While in copy mode

Efficient screen workflow:
  • On 2 monitors, start 2 fullscreen ssh sessions
  • Use screen -R -D on the first
  • Use screen -x on the second
You can now use screen as text based window manager. (awesome)

To use screen on the ADP1/G1/N1, use ConnectBot.

Also useful:


# Bind F11 and F12 (NOT F1 and F2) to previous and next screen window 
bindkey -k F1 eval prev fit 
bindkey -k F2 eval next fit 

vim / vimdiff notes

This message is for me only. I don't not expect you learn anything from this or even think this is useful.


Key
Action
Notes
ctrl+w, ctrl+w
switch windows
ctrl-w, J
Move the window down
do
diff obtain
doesn't work in 3-way?
dp
diff put
doesn't work in 3-way?
[c
previous difference
]c
next difference
:diffupdate
diff update
:syntax off
syntax off
zo
open folded text
zc
close folded text
:set paste
Disable auto-indent


v
select text
V
select lines
Ctrl-V
select vertical block
d
cut
y
yank (copy)
p
paste after the cursor
P
paste before the cursor
lv
selects an area equal to the yank buffer
lvp
replace paste
lNNvp
replace paste NN times
*y
yank to system clipboard


But this page is better: http://www.tuxfiles.org/linuxhelp/vimcheat.html
And the real reference: http://www.vim.org/htmldoc/quickref.html#quickref, accessible from inline help.
This one is awesome: http://jmcpherson.org/editing.html

Friday 12 June 2009

Boris Jabes (MS) told me that Visual Studio macros can be saved as UTF16 text file. I was shocked. How the hell I was ignoring that functionality, but it seems I'm not alone by the sheer number of hits when searching for [vsmproj] on the web (e.g. less than 100 except on Yahoo)

So here's how to convert your binary .vsmacros to utf16 .vsmproj project.

1. Open Macro Explorer in Visual Studio
2. Select a project or create a new one
3. Open the Properties Window (Alt+Enter)
4. In the properties, change the "storage format" from "binary (.vsmacros)" to "text (unicode)"

That is much more useful for sharing macros in a source control.

Archival price

I was considering buying a 50pk 4.5gig DVD spindle. It's ~15.40$ CAD for a good archival quality.
On the other side, a 1.5TB HD is 150$.

15.50$ / (50*4.5gb) = 6.9¢
150$ / 1500gb = 10¢

Taking in account that there's always lost space in DVD due to trying to fit it to its maximum space, the amount of time taken to format the data to fit in a DVD, the manual intervention of swaping the disks and the slow DVD write speed (compared to a SATA2 HD), I think it's not valuable to archive on DVD anymore, assuming you keep 2 copies of your data.

Wednesday 3 June 2009

Dell mini 10v

Coolness
1) With a 6 cells battery, this thing last a full day!
2) Jaunty supports hibernation, faster boot and *way* faster wifi connection. Hardy was way too slow to connect back to the wifi network.
3) If you take a colored top, you get the webcam for free. Mostly useless on a Atom processor anyway. :)

Issues
1) It took me a day to figure out how to page up/down key; kind of necessary when programming. Hint: FN key.
2) No video acceleration for the 945GME / GMA 950 until Karmic Koala 9.10. This video card is too unstable with UXA to be usable. That's quite disapointing.
3) The touchpad default configuration isn't great, I highly recommend a Logitech Nano VX.
4) With the 6 cells battery, the laptop is not level, making it hard to look at the monitor while the laptop is on a table and you are straight up. This is due to the fact that the monitor doesn't bend backward enough.
5) The dell ubuntu comes with Fluendo codecs and a custom shell launcher. My wife liked the launcher but the one in NBR is fine enough for her. TODO The codecs can be imported back into the new install if you install both OS side by side.

Survival kit
1) Install Ubuntu Jaunty 9.04 netbook remix (NBR). This netbook has a SDHC card reader so you can put it on a memory card from the stock ubuntu install.
2) Fix the palm check otherwise the mouse is constantly moving while typing on the keyboard.
Temporary fix:
DEVICE="SynPS/2 Synaptics TouchPad"
xinput list-props "$DEVICE"
xinput --set-int-prop "$DEVICE" "Synaptics Palm Detection" 8 1
xinput --set-int-prop "$DEVICE" "Synaptics Palm Dimensions" 32 10 10
First modify the file is /usr/share/hal/fdi/policy/20thirdparty/11-x11-synaptics.fdi as explained in:
http://ubuntu-snippets.blogspot.com/2009/03/multi-touch-for-anyall-synaptics.html

You can then install
sudo apt-get install gsynaptics
but it doesn't let you modify every settings..

3) If you kept the stock dell ubuntu 8.04 on a separate partition, fix the grub menu timeout to 1 second
sudo nano /boot/grub/menu.lst
Set the "timeout" line to 1.

4) Install Google Chrome!
http://dev.chromium.org/getting-involved/dev-channel

Update
- Better just turn off the touchpad after all, it's way too bad.
- Go in the bios and fix the Function keys as multimedia keys.
- I installed 2 gigs of RAM in it with the videos on youtube.

Friday 10 April 2009

Section synchronization

I was looking at a cleaver way to use interprocess communication and we (chromium) use shared memory with CreateFileMapping(). The main issue is synchronization. I was looking at using the section as an inherent synchronization tool but it fails miserably. I finally found the answer: « File mapping objects do not support the SYNCHRONIZE standard access right. »[1]

That would have been useful, even if it would have been limited to 4kb granularity or even just a global section lock. Sad. Going back to mutex. :(

[1]
http://msdn.microsoft.com/en-us/library/aa366559.aspx

EMF buffer idiocracy

On Windows XP, when creating an HDC from an EMF buffer with CreateEnhMetaFile():
  • SetDCBrushColor() and SetDCPenColor() calls are not recorded. Too bad for you.
  • When using GetStockObject(), DC_BRUSH and DC_PEN are useless and will return a white pen and a black pen respectively. Just don't use them.
  • Expect no-op from ExtTextOut(..., ETO_GLYPH_INDEX, ...) if GDI32!GdiInitializeLanguagePack hasn't been called.